`
zjf201172653
  • 浏览: 45370 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

java中静态块,静态属性,方法的加载顺序

阅读更多

java中静态块,静态属性,方法的加载顺序  转自http://blog.csdn.net/yufaw/article/details/7753669

 

这两天遇到几个类似的问题,就是一个程序到底是怎么运行的,而且这些问题很具有迷惑性,这里两个例子做分析( 实际上一切都在黑马的免费视频中有体现 ) !

问题一:如下代码的执行顺序是什么样的!一定理解:是执行的顺序(后面会给大家说一个误区)!

class Test
{

        int a = 5; 
        static int num = 4;                     //这是一个很简单的代码,但是你了解他的运行顺序吗
        Test()         

        }
        static {                                   // 那么可能你会有疑问,我该如何来去测试一下他们的执行顺序呢?
               
        }
        public static void main(String[] args){
                        
        }        
}

实际上你现在根本看不出来执行顺序,也很容易搞混淆,我们必须找出一种方便的手段去测试一下:

测试的方法:比如

static int num = 4; 这句代码,我们怎么知道他是不是执行了,可以这样写 static int num = 4; { system.out.println("执行了静态变量语句"); } 这样的话这段代码加载的时候,在控制台就能看到,是不是很方便!

接下来我们出发!--------->>
// 注意看,这里仅仅是一个普遍情况,特殊情况下面有总结:在下面的A ,B两种情况的总结非常的重要,一定要好好的看看! public classExten { static int num = 4; // 静态变量第二个 { num += 3; System.out.println("b"); } int a = 5;{ // 成员变量第三个 System.out.println("c"); } Exten() { // 类的构造函数,第四个加载 System.out.println("d"); } static { // 静态块,第一个加载 System.out.println("a"); } static void run() // 静态方法,调用的时候才加载// 注意看,e没有加载 { System.out.println("e"); } public static void main(String[] args) { new Exten(); }

一般顺序:静态块——>静态变量——>成员变量——>构造方法——>静态方法
1、静态代码块(只加载一次) 2、构造方法(创建一个实例就加载一次)3、静态方法需要调用才会执行,所以最后结果没有e


想知道顺序看看控制台!是不是一目了然了,

问题二:那么到这是不是已经完善了呢!请看下面问题很具有迷惑性!

 

  1. public class StaticInitTest {
  2. static int count = 2;      //定义静态变量(类变量)count,这个不是比较对象,下面的name是
  3. static String name = "我的黑马之路";     //定义静态变量
  4. static {              //通过静态初始化块为name变量初始化
  5. System.out.println("StaticInitTest的静态初始化块!");
  6. name = "黑马编程";
  7. }
  8. public static void main(String[] args) {
  9. System.out.println("count的值:"+StaticInitTest.count);
  10. System.out.println("name的值:"+StaticInitTest.name);
  11. }
  12. }
这是测试截图,请认真看看黑马程序员:JAVA中代码顺序,静态块-静态变量-成员变量-构造方法-静态方法,是如何加载的! - Budier_GreatMan - 黑马空间
 
黑马程序员:JAVA中代码顺序,静态块-静态变量-成员变量-构造方法-静态方法,是如何加载的! - Budier_GreatMan - 黑马空间
  • 你一看会发现就是啊,name的值改变了啊,这说明代码的执行改变了啊!
  • 实际上:刚才说了执行,什么是执行,什么是编译看明白自己就明白了!
  • 说实话,笔者研究这个问题一下午时间,为什么这么长时间,因为也没注意到这个问题,所以一直在深究内核的运作.....!
  • 下面我们看看为什么会出现这种问题把,为什么name的值会改变,是执行的顺序改变了吗!
  •    main方法中是什么,是不是只有打印语句,有没有操作上面的代码,没有把,其实是在不断的打印name这个静态对象的值

下面按前后顺序,分析谁在前,谁在后的执行结果 static { System.out.println("a静态块"); s = "我被编译了"; // 这里为什么不报错我们要理解Eclipse的编译顺序,从上到下依次编译,编译的时候就把所有的静态属性全部加载!

System.out.println(s);} // 这里你能获取到s吗? 系统会提示你,s还没有创创建,因为这里是第6行,你的对象在第8行才创建,编译不通过;

static String s = "你只是在打印我"; //这里才创建的String对象,按编译顺序s是多少?是不是变成了 "你只是在打印我"最终main函数中只是打印了s ,打印就是"你只是在打印我"

现在换位置:  static String s = "你只是在打印我" ; //编译通过先创建了String类型的s; s是多少?是不是"你只 是在打印我"

static { s = "我被编译了" ; System.out.println(s); //Eclipse从上到下依次编译,,不是执行,是编译,编译到这,这里s是谁 ?是不是"我被编译了" } 然后到这又把这个s直接打印了出来,打印结果肯定会变成,"我被编译了" !!

问题:有值就是执行过了吗?   
总结:因为main方法中都是打印语句,只是在-----打印编译后加载的值-----而已;

打印不打印,name和s的值都在那里!注意不注意,name和s都是静态的!编译加载而已!

static String s = "静态String"; { System.out.println("静态String"+s); }
static int a = 5;
{
s  = "非静态int";
System.out.println("静态int变量");
}//还要注意的问题就是,在a中到底有没有给s赋值,很显然s的值此时未变,new的时候才执行到,为什么,请看下面的大总结!

 

实际上,以上的所有问题加起来就得到的完整的答案,你如果看到了这里恭喜你,笔者费劲总结的最终的正确的结果就在下面:


先把内在的执行规律简述:

  •           静态变量这个问题是最不容易搞明白的问题,静态变量只加载一次,以后不论你怎么new不会再加载
  •           而且注意:静态块也是仅加载一次,
  •            静态变量后大括号内有代码的话,new一次执行一次。
  •            静态块加载的时候大括号内的语句就执行完毕,以后不会执行。

是不是比较复杂,光看特性就已经复杂了,这里有些的同学可能就会想了,那这两个的执行顺序是怎么样的呢,这里非常的迷惑人,因为各种情况你得到的测试结果可能都不一样
不过他们还是有顺序的,只不过分情况对待!

 


大补充:   
A、类的初始化顺序如下:
->1、为静态属性分配内存并赋值(后面大括号语句不执行,这里是初始化,只是添加变量和值) 
         或  执行静态代码块(立刻执行大括号里面的语句)
          为什么这样说呢,因为谁在前先加载谁,包括静态属性之间,和静态块之间的顺序,
          但是注意,虽然顺序都可以当第一,但是静态块、静态属性执行的东西完全不一样,怎么不一样,已经写上去了自己看
      (笔者注:这个问题,在花了很多时间的推敲后,最终有了答案,前后花了不少的时间去运行代码,修改各种情况,也有同学参与了进来,所以大家对我们付出的努力应该尊重啊)
->2、非静态属性分配内存并赋值
->3、构造方法(实际上这个先于非静态属性调用到,只是构造方法里面的语句暂停执行,等到非静态属性加载完才执行)
->4、执行非静态代码块 或 静态方法(都是调用了才加载)。



B、类的代码(大括号内的语句)执行顺序:   当你创建了对象的时候才会用到各个属性和变量对不对,这里就是这个顺序
->1、执行静态代码块(大括号包含的语句立刻执行,绝对是第一位的执行,没有能和它平级的)
->2、静态属性 (第二位执行
->3、为非静态属性分配内存并赋值(大括号内语句第三位执行)
->4、构造函数
->执行非静态代码块 或 静态方法(都是调用了才加载)。
  


这样的话是不是非常的清晰呢了!这才是所有代码加载的顺序啊,以后对于程序的执行就会有更深的理解了 !
分享到:
评论
1 楼 xiaoyao3857 2014-04-20  
"从接下来我们出发"下的第一个程序,总结的加载顺序不太对,静态块确实是第一个,但其后不一定是静态成员变量->成员变量,静态变量、成员变量谁在前、谁在后跟在程序声明的顺序有关

"    静态变量这个问题是最不容易搞明白的问题,静态变量只加载一次,以后不论你怎么new不会再加载
          而且注意:静态块也是仅加载一次,
           静态变量后大括号内有代码的话,new一次执行一次
           静态块加载的时候大括号内的语句就执行完毕,以后不会执行。"
还有大补充那块说得比较好

相关推荐

    java面试题静态加载顺序构造方法

    java面试题静态加载顺序构造方法 继承与static 面试题目如下:请写出程序执行完成之后的结果。 package extend; public class X { Y y=new Y(); static{ System.out.println("tttt"); } X(){ System....

    java 面试题 总结

     final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句结构的一部分,表示总是执行。 finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的...

    JAVA基础课程讲义

    静态初始化块(经常用来初始化类,加载类信息时执行!) 67 package 68 JDK中的主要包 68 import 68 eclipse的使用 69 继承(extend, inheritance) 70 为什么需要继承?继承的作用? 70 继承介绍 70 如何实现继承? ...

    疯狂JAVA讲义

    学生提问:为什么静态内部类实例方法也不能访问外部类的实例属性呢? 207 学生提问:接口里是否能定义内部接口? 208 6.7.3 使用内部类 208 学生提问:既然内部类是外部类的成员,是否可以为外部类定义子类,在...

    Java面试宝典-经典

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

    Java面试宝典2010版

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

    杰普学习corejava总结笔记

    类加载,同时初始化类中静态的属性(赋默认值) 2.执行静态代码块 3.分配内存空间,同时初始化非静态的属性(赋默认值) 4.调用父类构造器(注意调用父类构造器之前已经给父类的非静态的属性显示赋值,如果有显示赋值的话...

    java面试题大全(2012版)

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

    最新Java面试宝典pdf版

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

    Java开发技术大全 电子版

    3.7.2静态方法和实例方法的区别134 3.7.3静态代码块136 3.7.4再论静态成员变量137 3.8main()方法和命令行参数139 3.9结束方法141 3.10本地方法141 3.11本章小结144 第4章继承与多态145 4.1继承的基本原理145...

    java面试题

    51.5. java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 25 52. 数据连接池 25 52.1. 连接池的基本原理: 25 52.2. 连接池的工作机制 25 52.3. 建立连接池 26 ...

    Java面试笔试资料大全

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

    超级有影响力霸气的Java面试题大全文档

     final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句结构的一部分,表示总是执行。 finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的...

    java面试宝典2012

    抽象类中是否可以有静态的main方法? 16 21、写clone()方法时,通常都有一行代码,是什么? 16 22、面向对象的特征有哪些方面 17 23、java中实现多态的机制是什么? 18 24、abstract class和interface有什么区别? ...

    JAVA面试宝典2010

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

    Java面试宝典2012新版

    抽象类中是否可以有静态的main方法? 15 21、写clone()方法时,通常都有一行代码,是什么? 15 22、面向对象的特征有哪些方面 15 23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? ...

Global site tag (gtag.js) - Google Analytics