class A
{
public static final A a=null;//改为int a = 1;//下面的静态块就不执行
static{System.out.println("A000000000");}
}
public class Test
{
public static void main(String[] args)
{
Object o=A.a;
}
}
通过javap -c Test查看经过编译后的字节码就明白了
不单单是null的问题,但null确实是问题之一
更重要的一个问题是会写到A.class常量池中的类型是有限的:String和几个基本类型
而A.a的类型是A
如果将a的类型改为String,为null仍然会去getstatic
如果a的类型为String,且有一个字符串值,那么A就使用ldc指令直接从B的常量池中取值,这表示a的值在编译的时候已经放到A.class中了。
假如A.a的值是编译期常量,如果Test类中使用了A.a,编译的是时候在Test.class存的就不是A.a的符号引用,而直接是A.a的值,这就不是主动使用了。
当然,这也并不是说所有String和几个基本类型的常量就会放到B的常量池中去
比如a是int类型,其值为32767,使用的就是sipush 32767,表示操作数直接跟在操作码后面
如果值为32768,还是会从常量池用ldc指令取值
但,不管如何,这种值都放到了Test.class中,要么在Test的常量池中,要么跟在字节码后面作为参数