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

在Java中何时执行二进制运算符?,java,jvm,bytecode,Java,Jvm,Bytecode,我试图理解java字节码。我从一个简单的例子开始: public class Test { public static void main(String args[]) { System.out.println(2 + 1); } } 我编写了这个类: javac Test.java 然后我尝试在.class上创建一个javap,如下所示: javap -c Test 这给了我这个: Compiled from "Test.java" public

我试图理解java字节码。我从一个简单的例子开始:

public class Test
{
    public static void main(String args[])
    {
        System.out.println(2 + 1);
    }
}
我编写了这个类:

javac Test.java
然后我尝试在.class上创建一个
javap
,如下所示:

javap -c Test
这给了我这个:

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        
}
看看我的源代码和这个字节码,看起来javac已经为这个语句完成了加法操作:

2+1
并要求jvm返回该常量


如果我的理解错了,有人能纠正我吗?javac在jvm上实际运行之前,是否对
+
-
*
等执行编译操作?如果是这样,怎么办?

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

请参见以下内容:

有些表达式的值可以在编译时确定。这些都是常量表达式

有关构成常量表达式的内容,请参见

常量表达式是表示原语类型的值或字符串的表达式,该值或字符串不会突然完成,并且仅使用以下内容组成:

  • 基元类型的文字和字符串[…]类型的文字
  • 加法运算符+和- [……]

它是一个常量,在编译时进行了优化,“如何”是一个非常简单的数学问题。编译器知道这些是数字,不能更改,并且可以添加。所以所有常量表达式都由编译器解析?@batman是的,但请注意,
1+2+i
i+1+2
将编译为
3+i
i+1+2
。这是因为在第一种情况下的操作顺序是
(1+2)+i
,所以
(1+2)
可以由编译器优化,但是在
(i+1)+2
的情况下
(i+1)
编译器在编译时无法知道
i
的值,所以它不会优化您的代码。@Pshemo:这是一点有趣的信息,括号如何帮助编译器优化。谢谢另一个实际用法是在多行上定义长字符串,例如SQL查询。或者一个持续时间,比如一天,单位为24L*60L*60L*1000L。编译器不必优化常量表达式,只是鼓励它这样做,而且在实践中确实如此。
2+1