二进制运算符执行何时在Java中执行?

bat*_*man 10 java jvm bytecode

我正在尝试理解java字节码.我从简单的例子开始:

public class Test
{
    public static void main(String args[])
    {
        System.out.println(2 + 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

我编译了这个类:

javac Test.java
Run Code Online (Sandbox Code Playgroud)

然后我尝试javap在.class上像这样:

javap -c Test
Run Code Online (Sandbox Code Playgroud)

这给了我这个:

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

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: iconst_1      
       4: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
       7: return        
}
Run Code Online (Sandbox Code Playgroud)

除了这一行,我能够理解它:

public static void main(java.lang.String[]);
. . . 
3: iconst_1    
. . .
Run Code Online (Sandbox Code Playgroud)

看看我的源代码和这个字节代码,看起来像javac已经完成了对此语句的添加操作:

2+1
Run Code Online (Sandbox Code Playgroud)

并要求jvm返回该常量.

如果我的理解错了,有人可以纠正我吗?是否执行的javac编译上的操作+,-,*等它实际上在JVM上运行过吗?如果是这样的话?

JB *_*zet 24

2 + 1是编译时常量表达式.编译器本身在字节码中将其替换为3.

请参阅Java语言规范,其中说:

某些表达式具有可在编译时确定的值.这些是常量表达式.

有关常量表达式的构成,请参见本章

常量表达式是表示基本类型值的表达式或不突然完成的字符串,仅使用以下内容组成:

  • 原始类型的文字和String类型的文字[...]
  • 添加剂操作符+和 - [...]

  • @batman是的,但请注意`1 + 2 + i`和`i + 1 + 2`将被编译为`3 + i`和`i + 1 + 2`.这是因为操作的顺序,在第一种情况下是`(1 + 2)+ i`所以`(1 + 2)`可以由编译器优化,但是在`(i + 1)+ 2`的情况下` (i + 1)`编译器在编译时无法知道`i`的值,因此它不会优化你的代码. (6认同)
  • 编译器没有_have_来优化常量表达式,它只是鼓励并且在实践中做到了. (2认同)