Sth*_*ita 86 java static access-modifiers
class Test{
public static void main(String arg[]){
System.out.println("**MAIN METHOD");
System.out.println(Mno.VAL);//SOP(9090);
System.out.println(Mno.VAL+100);//SOP(9190);
}
}
class Mno{
final static int VAL=9090;
static{
System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道static
在加载类时执行的块.但是在这种情况下,类中的实例变量Mno
是final
因为static
块没有执行.
为什么会这样?如果我删除它final
,它会工作正常吗?
首先分配哪个内存,static final
变量或static
块?
如果由于final
访问修饰符而没有加载类,那么变量如何获取内存?
Mar*_*nik 132
static final int
字段是一个编译时间常数和它的值被硬编码到而不到其原点的参考目标类;具体细节,编译后的字节码对应于:
public static void main(String arg[]){
System.out.println("**MAIN METHOD");
System.out.println(9090)
System.out.println(9190)
}
Run Code Online (Sandbox Code Playgroud)
一旦删除final
,它就不再是编译时常量,并且上述特殊行为不适用.在Mno
像您期望的类加载和它的静态初始化执行.
未加载类的原因VAL
是final
AND是用常量表达式初始化(9090).如果且仅当满足这两个条件时,在编译时评估常量并在需要时"硬编码".
要防止在编译时计算表达式(并使JVM加载您的类),您可以:
删除最终关键字:
static int VAL = 9090; //not a constant variable any more
Run Code Online (Sandbox Code Playgroud)或者将右侧表达式更改为非常量(即使变量仍然是最终的):
final static int VAL = getInt(); //not a constant expression any more
static int getInt() { return 9090; }
Run Code Online (Sandbox Code Playgroud)如果你看到生成的字节码使用javap -v Test.class
,main()出现如下:
public static void main(java.lang.String[]) throws java.lang.Exception;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String **MAIN METHOD
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: sipush 9090
14: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
17: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
20: sipush 9190
23: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
26: return
Run Code Online (Sandbox Code Playgroud)
您可以在" 11: sipush 9090
"中清楚地看到直接使用静态最终值,因为Mno.VAL是编译时常量.因此,不需要加载Mno类.因此,不执行Mno的静态块.
您可以通过手动加载Mno来执行静态块,如下所示:
class Test{
public static void main(String arg[]) throws Exception {
System.out.println("**MAIN METHOD");
Class.forName("Mno"); // Load Mno
System.out.println(Mno.VAL);
System.out.println(Mno.VAL+100);
}
}
class Mno{
final static int VAL=9090;
static{
System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10729 次 |
最近记录: |