最终的静态变量操作,编译还是运行时?

最终的静态变量操作是在运行时还是编译时发生的? 例如:

public static final int ID_1 = 1; public static final int ID_2 = 2; public static int test(){ return ID_1 + ID_2; // Does this addition execute in compile or runtime ? } 

这里有一个提示: https : //docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

它说:

如果将基本类型或字符串定义为常量并且在编译时已知该值,则编译器会将代码中的常量名称替换为其值。

因此,一旦完成并且您在方法中最终得到1 + 2 ,那么优化它也是合乎逻辑的,并且只需在编译时使用3

为了在实践中certificate它,您可以编译代码然后反编译它以查看正在发生的事情。

我尝试使用JD-GUI,这是我在反编译代码时得到的:

  public class TestCompileOrRuntime { public static final int ID_1 = 1; public static final int ID_2 = 2; public static int test() { return 3; } } 

所以在这种情况下看起来编译器正在编译时解决操作。

这是一个编译时操作(我在下面得到一个方法本地iconst_3 )。 我们可以用javap -v直接检查生成的字节码。 我创建了一个Main类,

 package com.stackoverflow; public class Main { public static final int ID_1 = 1; public static final int ID_2 = 2; public static int test() { return ID_1 + ID_2; // <-- Compile time. } } 

然后运行javap -v来获取

 Classfile /home/efrisch/workspace/StackOverflow/bin/com/stackoverflow/Main.class Last modified Aug 22, 2015; size 410 bytes MD5 checksum 6ba30603e8f16cbebc681a84061d38c3 Compiled from "Main.java" public class com.stackoverflow.Main minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Class #2 // com/stackoverflow/Main #2 = Utf8 com/stackoverflow/Main #3 = Class #4 // java/lang/Object #4 = Utf8 java/lang/Object #5 = Utf8 ID_1 #6 = Utf8 I #7 = Utf8 ConstantValue #8 = Integer 1 #9 = Utf8 ID_2 #10 = Integer 2 #11 = Utf8  #12 = Utf8 ()V #13 = Utf8 Code #14 = Methodref #3.#15 // java/lang/Object."":()V #15 = NameAndType #11:#12 // "":()V #16 = Utf8 LineNumberTable #17 = Utf8 LocalVariableTable #18 = Utf8 this #19 = Utf8 Lcom/stackoverflow/Main; #20 = Utf8 test #21 = Utf8 ()I #22 = Utf8 SourceFile #23 = Utf8 Main.java { public static final int ID_1; descriptor: I flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL ConstantValue: int 1 public static final int ID_2; descriptor: I flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL ConstantValue: int 2 public com.stackoverflow.Main(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #14 // Method java/lang/Object."":()V 4: return LineNumberTable: line 4: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/stackoverflow/Main; public static int test(); descriptor: ()I flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=0, args_size=0 0: iconst_3 1: ireturn LineNumberTable: line 9: 0 LocalVariableTable: Start Length Slot Name Signature } SourceFile: "Main.java"