Java + 运营商

Java + Operator

我无法理解加法运算符或 short 数据类型的概念。

据说是这样;

short a = 1;
short b = 2;
short c = a + b;

不会编译,因为加法运算符总是将 shortchartbyte 数据类型转换为 int,我理解这一点。但是这个;

short c = 1 + 2;

工作得很好。因此,如果加法运算符自动将 short 转换为 int,然后应用结果(当然,结果将是 int),为什么这样可以正常工作?

编辑: 这个问题与 Primitive type 'short' - casting in Java 不重复,因为我了解转换过程。另外,这个问题谈到了数据类型的转换,因为我的问题与 int 文字有关。

据我了解,Java 支持 int 和 long 的 +,但按照规定,不支持 short。没有自动类型转换,因为该操作被指定为对 int 或 long 数据类型执行。

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2

如果你想得到一个有效的结果,并且知道结果不会导致溢出,你可以转换结果:

short a = 1;
short b = 2;
short c = (short)(a + b);

1 + 2 是常量表达式,而 a + b 不是。
这关系到他们的评价。
第一个会在编译时完成,第二个会在运行时完成。

JLS 8 状态:

15.28. Constant Expressions

A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

  • Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

  • Casts to primitive types and casts to type String (§15.16)

  • The unary operators +, -, ~, and ! (but not ++ or --) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)

  • The multiplicative operators *, /, and % (§15.17)

  • The additive operators + and - (§15.18)

........................

这里:

short c = 1 + 2;

1 + 2由两个int文字和一个加法运算符组成。
所以它被认为是一个常量表达式。
常量表达式在编译时求值。
所以 short c 被评估为 3

这是一个示例 class :

package Whosebug;

public class EvaluationClass {

    public void foo(){
       short c = 1 + 2;
    }
}

这里是反汇编代码:

Compiled from "EvaluationClass.java"
public class Whosebug.EvaluationClass {
  public Whosebug.EvaluationClass();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()
       4: return

  public void foo();
    Code:
       0: iconst_3
       1: istore_1
       2: return
}

我们可以看到 0: iconst_3 指令将 3 int 加载到堆栈上。


而这里:

short a = 1;
short b = 2;
short c = a + b;

a + b 仅在运行时计算,因为 ab 不是常量值。
他们的价值观确实随时都可能改变。
请注意,编译器不会试图通过阅读每个语句来猜测 ab 是否有效变异。
它认为它可能因此仅在运行时评估 a + b

现在在这种情况下,为什么 a + b 不产生 short 而产生 int
因为 JLS 8 指定 :

4.2.2. Integer Operations

If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).

Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.


附带说明一下,如果将代码更改为 ab constants:

final short a = 1;
final short b = 2;
short c = a + b;

现在可以正常编译,因为 a + b 将被评估为常量表达式 (3)。