参考:http://hllvm.group.iteye.com/group/topic/37682
http://blog.csdn.net/javakuroro/article/details/6817520
http://blog.csdn.net/qq1623267754/article/details/36190715
=======================================================================
首先来说,普通的静态变量赋初始值是在<clinit>中,准备阶段为类变量分配内存,并赋默认值(boolean设置为false,int设为0,double设为0.0d等)。
而常量静态变量 (static final)在Class文件里对应的field_info里带有ConstantValue属性,里面记录了该字段的常量值(在常量池里的编号),在类的初始化阶段会对类里的带有
ConstantValue的final static变量做初始化(第6步),这在调用<clinit>()之前。
final修饰的属性的初始化可以在编译期,也可以在运行期,初始化后不能被改变。 static修饰的属性的初始化在编译期(类加载的时候),初始化后能改变。对于基本类型数据,final会
将值变为一个常数(创建后不能被修改);但是对于对象句柄(亦可称作引用或者指针),final会将句柄变为一个常数(进行声明时,必须将句柄初始化到一个具体的对象。而且不能
再将句柄指向另一个对象。但是,对象的本身是可以修改的。这一限制也适用于数组,数组也属于对象,数组本身也是可以修改的。方法参数中的final句柄,意味着在该方法内部,我
们不能改变参数句柄指向的实际东西,也就是说在方法内部不能给形参句柄再另外赋值)。
1.import java.util.Random; 2. 3.//这个例子想说明一下static final 与 final的区别 4.public class StaticAndFinalTest { 5. 6. private static Random rand = new Random(47); //47作为随机种子,为的就是产生随机数。 7. 8. private final int a = rand.nextInt(20); 9. 10. private static final int B = rand.nextInt(20); 11. 12. public static void main(String[] args) { 13. StaticAndFinalTest sf = new StaticAndFinalTest(); 14. System.out.println("sf : " + "a=" + sf.a); 15. System.out.println("sf : " + "B=" + sf.B); 16. System.out.println("------------------------------"); 17. StaticAndFinalTest sf1 = new StaticAndFinalTest(); 18. System.out.println("sf1 : " + "a=" + sf1.a); 19. System.out.println("sf1 : " + "B=" + sf1.B); 20. } 21. 22.}
运行结果:
- sf : a=15
- sf : B=18
- --------------
- sf1 : a=13
- sf1 : B=18
可以看到,在sf和sf1对象中,a的值不是唯一的,但B的值是不会通过创建sf1对象而改变。这是因为它是static,在装载时已被初始化,而不是每次创建新对象时都初始化。