Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1670304
  • 博文数量: 695
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4027
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-20 21:22
文章分类

全部博文(695)

文章存档

2018年(18)

2017年(74)

2016年(170)

2015年(102)

2014年(276)

2013年(55)

分类: Java

2017-11-06 11:29:01

假设一个类变量的定义为: publicstaticintvalue=3

那么变量value在准备阶段过后的初始值为0,而不是3,因为这时候尚未开始执行任何Java方法,而把value赋值为3的 publicstatic指令是在程序编译后,存放于类构造器 ()方法之中的,所以把value赋值为3的动作将在初始化阶段才会执行。所以在执行构造函数之前 value的值是默认值0,在执行类构造函数中,会优先赋值静态变量(静态变量按赋值顺序赋值)
如果类字段的字段属性表中存在 ConstantValue属性,即同时被final和static修饰,那么在准备阶段变量value就会被初始化为ConstValue属性所指定的值。


点击(此处)折叠或打开

  1. public class TestStatic {
  2.     public static void main(String []args){
  3.         staticFunticon();
  4.     }    
  5.       static TestStatic s = new TestStatic();
  6.     static
  7.     {
  8.         System.out.println("1");
  9.     }
  10.     {
  11.         System.out.println("2");
  12.     }
  13.     public TestStatic(){
  14.         System.out.println("3");
  15.         System.out.println("a=:"+a+" b=:"+b);
  16.     }
  17.     public static void staticFunticon(){
  18.         System.out.println("4");        
  19.     }
  20.     int a =110;
  21.     static int b =112;

  22. }

点击(此处)折叠或打开

  1. 2
  2. 3
  3. a=:110 b=:0
  4. 1
  5. 4
先上了题和答案,看能否答对
在上两段话,自己对照答案去理解,最后上改题的分析过程
什么情况下需要开始类加载过程的第一个阶段:"加载"。虚拟机规范中并没强行约束,这点可以交给虚拟机的的具体实现自由把握,但是对于初始化阶段虚拟机规范是严格规定了如下几种情况,如果类未初始化会对类进行初始化。
一、
  1. 创建类的实例
  2. 访问类的静态变量(除常量【被final修辞的静态变量】原因:常量一种特殊的变量,因为编译器把他们当作值(value)而不是域(field)来对待。如果你的代码中用到了常变量(constant variable),编译器并不会生成字节码来从对象中载入域的值,而是直接把这个值插入到字节码中。这是一种很有用的优化,但是如果你需要改变final域的值那么每一块用到那个域的代码都需要重新编译。(调用数组也不会主动初始化)
  3. 访问类的静态方法
  4. 反射如(Class.forName("my.xyz.Test"))
  5. 当初始化一个类时,发现其父类还未初始化,则先出发父类的初始化(对于访问静态字段,初始化父类的时候只有直接定义这个字段的类才会初始化)
  6. 虚拟机启动时,定义了main()方法的那个类先初始化


二、
1.若要加载类A,则先加载执行其父类B(Object)的静态变量以及静态语句块(执行先后顺序按排列的先后顺序)

2.然后再加载执行类A的静态变量以及静态语句块。(并且12步骤只会执行1)
3.若需实例化类A,则先调用其父类B的构造函数,并且在调用其父类B的构造函数前,依次先调用父类B中的非静态变量及非静态语句块.最后再调用父类B中的构造函数初始化。
4.然后再依次调用类A中的非静态变量及非静态语句块.最后调用A中的构造函数初始化。并且34步骤可以重复执行)
5.而对于静态方法和非静态方法都是被动调用,即系统不会自动调用执行,所以用户没有调用时都不执行,主要区别在于静态方法可以直接用类名直接调用(实例化对象也可以),而非静态方法只能先实例化对象后才能调用。

运行结果分析:
首先执行main函数中的staticFunticon,因为调用静态方法了按照 一、6(虚拟机启动时,定义了main()方法的那个类先初始化),会初始化该类,初始化之前要先 加载、连接(验证、准备、解析)、初始化、使用、卸载,按照二、1(若要加载类A,则先加载执行其父类B(Object)的静态变量以及静态语句块(执行先后顺序按排列的先后顺序))先执行static TestStatic s = new TestStatic();这一句,因为这里new了一个实例对象,所以就会接着触发构造函数(如果没有new的话构造函数是在static变量和static语句块之后的,这里还有说一句因为static TestStatic s = new TestStatic()在static int b=110之前,所以b还没有初始化,在准备阶段所有的static变量都是先以默认值赋值的,所以这里的b现在是默认值(0))执行构造函数前参照二、4(然后再依次调用类A中的非静态变量及非静态语句块.最后调用A中的构造函数初始化)也就是说类中非静态成员和非静态代码块要在类构造函数前执行。所以这里先执行了System.out.println("2");,a=110;接着执行构造函数,所以输出的a=110,b=0;然后在继续向下执行static代码块System.out.println("1");最后回到main函数中执行staticFunticon方法


点击(此处)折叠或打开

  1. class SuperClass {
  2.     static {
  3.         System.out.println("superclass init");
  4.     }
  5.     public static int value = 123;
  6. }
  7.  
  8. class SubClass extends SuperClass {
  9.     static {
  10.         System.out.println("subclass init");
  11.     }
  12. }
  13.  
  14. public class Test {
  15.     public static void main(String[] args) {
  16.         System.out.println(SubClass.value);// 被动应用1
  17.         SubClass[] sca = new SubClass[10];// 被动引用2
  18.     }
  19. }
  20. 程序运行输出 superclass init
  21.                             123


点击(此处)折叠或打开

  1. public class InitialOrderTest {
  2.     /* 静态变量 */
  3.     public static String staticField = "静态变量";
  4.     public static int a = 1;
  5.     /* 变量 */
  6.     public String field = "变量";
  7.     /* 静态初始化块 */
  8.     static {
  9.         System.out.println(staticField);
  10.         System.out.println("静态初始化块");
  11.         System.out.print("a:"+a);
  12.     }
  13.     /* 初始化块 */
  14.     {
  15.         System.out.println(field);
  16.         System.out.println("初始化块");
  17.     }

  18.     /* 构造器 */
  19.     public InitialOrderTest() {
  20.         System.out.println("构造器");
  21.     }

  22.     public static void main(String[] args) {
  23.         //new InitialOrderTest();
  24.     }
  25. }



阅读(1156) | 评论(0) | 转发(0) |
0

上一篇:深刻理解ThreadLocal

下一篇:mysql面试

给主人留下些什么吧!~~