问题
在jake wharton的Twitter上看到他提得这样一个问题:
于是测试了一下,发现很有趣,于是记录下来。
测试类
两个测试类如下1
2
3class TestMethodA {
static String name = "akioss";
}
1 | class TestMethodB { |
查看字节码
通过javap指令查看两个类的字节码
classA
1 | class com.akioss.TestMethodA { |
可以看到除了默认的构造方法之外,还有一个静态代码块,执行了putstatic指令
classB
1 | class com.akioss.TestMethodB { |
Tips
之所以会产生这样的情况,就是在于final
修饰符(好吧,这是废话 - -!),在讲明为何会出现上述情况之前,先来温习一下static
和final
两个的区别吧。
- static:static修饰成员变量时,并不会随着类的实例化再去分配空间,从上边
putstatic
指令也可以看出来,但有一点它是变量。 - final+static:final和static一同使用,那么被其修饰的值便成了
全局常量
,即不可变了。
所以大胆猜测final+static
修饰的值一开始就会被jvm分配到常量池,不会在类中去作这一步操作。而static
修饰的成员变量,实际是在类实例化的时候执行了一段static代码块,将成员变量putstatic
,为了验证,改写了一下TestMethodA.java
TestMethodA
1
2
3
4
5
6
7class TestMethodA {
static String name = "akioss";
static{
name = "jake";
}
}
其字节码
1 | class com.akioss.TestMethodA { |
可以发现,同一个类中,在static代码块中对静态成员变量name
赋值时,与声明name
成员变量走的同一代码块。