Когда выполнение бинарных операторов происходит на Java?

Я пытаюсь понять java-байтовый код. Я начал с простого примера:

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

Я скомпилировал этот класс:

javac Test.java

И затем я попытался сделать javap в .class следующим образом:

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        
}

Я мог бы понять из этого, кроме этой строки:

public static void main(java.lang.String[]);
. . . 
3: iconst_1    
. . .

глядя на мой источник и этот байт-код, похоже, что javac уже выполнил операцию добавления для этого оператора:

2+1

и попросить jvm вернуть эту константу.

Может кто-нибудь исправить меня, если мое понимание ошибочно? Выполняет ли javac операцию по компиляции для +, -, * и т.д., Прежде чем она начнет работать на jvm? Если да, то как?

Ответ 1

2 + 1 - выражение постоянной времени компиляции. Сам компилятор заменяет его на 3 в байтовом коде.

См. Java Language Specification, в котором говорится:

Некоторые выражения имеют значение, которое можно определить во время компиляции. Это постоянные выражения.

Смотрите эту другую главу для того, что представляет собой постоянное выражение

Постоянное выражение представляет собой выражение, обозначающее значение примитивного типа или String, которое не завершается внезапно и составлено с использованием только следующего:

  • Литералы примитивного типа и литералов типа String [...]
  • Аддитивные операторы + и - [...]