A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 丘凤光 金牌黑马   /  2013-4-29 14:00  /  2952 人查看  /  14 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

张老师的ppt反射的基石——>Class类有提到了:静态代码块不是在类加载时被调用的,而是第一个实例对象被创建时才执行的。

但是我讲这个知识点在18期分享的时候,有朋友提出了不同的观点,测试了一下,好像确实和老师说的有点不同,帖子没人再回答沉了,重新整理希望在云四能得到正确的解析
测试代码如下
  1. /*
  2. 需求:测试构造代码块、静态构造代码块的执行顺序。
  3. */

  4. class StaticCode1
  5. {
  6.         static
  7.         {
  8.                 System.out.println("StaticCode1——————静态代码块");
  9.         }
  10.         {
  11.                 System.out.println("StaticCode1————————代码块");
  12.         }
  13. }

  14. class StaticCode
  15. {
  16.         static
  17.         {
  18.                 System.out.println("StaticCode静态代码块——————");
  19.         }
  20.         {
  21.                 System.out.println("StaticCode代码块————————");
  22.         }
  23. }

  24. class StaticCodeDemo
  25. {
  26.         static
  27.         {
  28.                 System.out.println("StaticCodeDemo静态代码块1");
  29.         }
  30.         {
  31.                 System.out.println("StaticCodeDemo代码块");
  32.         }
  33.         public static void main(String[] args)
  34.         {
  35.                 //连续创建两个StaticCode类的对象,静态代码块之执行一次,非静态代码块执行两次
  36.                 new StaticCode();
  37.                 new StaticCode();

  38.                 //同一个类中有多个静态代码块,按由上到下顺序执行
  39.                 new StaticCodeDemo();

  40.                 System.out.println("over");
  41.         }
  42.         static
  43.         {
  44.                 System.out.println("StaticCodeDemo静态代码块2");
  45.         }
  46. }
复制代码
运行结果

将main函数中的 new StaticCodeDemo();
去掉后结果
StaticCodeDemo静态代码块运行非静态代码块没有运行。
  1. StaticCodeDemo静态代码块1
  2. StaticCodeDemo静态代码块2
  3. StaticCode静态代码块——————
  4. StaticCode代码块————————
  5. StaticCode代码块————————
  6. over
复制代码
按老师的观点,既然StaticCodeDemo的静态代码块执行了应该也就是第一个实力对象被创建了,既然对象创建了非静态代码块就应该执行啊。测试中没有执行。
求解

(有可能不经常上网,版主认为有人的回答合理的帮忙改为以解决哈)—

评分

参与人数 1技术分 +2 收起 理由
HM汪磊 + 2

查看全部评分

14 个回复

倒序浏览
啊哈 ,还在纠结这个问题啊。我也很是印象深刻。
先帮你顶下帖吧,我还没看到张老师的反射知识。
我觉得解决这个问题需要搞清楚以下问题:
1.分清楚类加载和实例对象创建的时机
2.仔细理解张老师说的第一个实例对象,到底说的是哪个实例对象。比方说某个类的,或者主函数所在类的?
以上是我的理解,你已经学过相关知识,看能否给你些提示。
等我学到相关知识,一定回头来看看。
回复 使用道具 举报
黑马伍哲沂 发表于 2013-4-29 14:44
啊哈 ,还在纠结这个问题啊。我也很是印象深刻。
先帮你顶下帖吧,我还没看到张老师的反射知识。
我觉得解 ...

哈哈,还是你帮我找到的问题呢,谢谢哈。有问题不弄清楚会觉得不踏实滴
回复 使用道具 举报
按我的理解应该没有错啊。
在创建实例对象,即new的时候执行构造代码块,他优先于任何构造函数。因此没new,就不会执行构造代码块;
而静态代码块是在类加载的时候执行的。
类加载的时机:就是谁用到了我这个类的内容,仅仅创建引用是不会加载类的;
比如:StaticCode code=null;这样就不会发生类加载。。。

评分

参与人数 1技术分 +1 收起 理由
HM汪磊 + 1

查看全部评分

回复 使用道具 举报
这个貌似是有点不是很严谨。
比如 当这个类中有静态方法时,在第一次调用静态方法时就执行静态代码块
以后在无论是再创建对象 还是再调用静态方法否不会在运行 静态代码块

所以我感觉严谨点说应该是 在class文件加载进内存的时候执行静态代码块   
回复 使用道具 举报
如果要得到类的字节码有三种方式:1.Class.forName(); 2.类名.class 3.对象名.getClass();
第一种就是类加载时static执行了,而第二种则没有执行,第三种对象都出来了static和匿名构造函数肯定执行了。我感觉怪就怪在第二种方式。
按照这样的逻辑我们使用第一种方式的时候static代码块执行了,使用第二种获取到字节码然后调用其getMethod()方法也应该执行,但是张老师却说没有,经过测试的确也是如此,我想他大概想表达的奇怪就是这个意思。求解释,我也不知道为什么会这样?
测试代码:
  1. package cn.itcast.itheima;

  2. import java.lang.reflect.Method;

  3. class StaticCode1{
  4.         private int age;
  5.         static{
  6.                 System.out.println("staticcode1--a");
  7.         }
  8.        
  9.         {
  10.                 System.out.println("staticcode1--b");
  11.         }
  12.         public int getAge(){
  13.                 return age;
  14.         }
  15.         public void setAge(int age){
  16.                 this.age = age;
  17.         }
  18. }

  19. public class StaticTest {

  20.         /**
  21.          * @param args
  22.          */
  23.        
  24.         public static void main(String[] args) {
  25.                 // TODO Auto-generated method stub
  26.                
  27.                 try {
  28.                         /*Class cls = StaticCode1.class;
  29.                         Method[] methods = cls.getMethods();
  30. */                        Class.forName("cn.itcast.itheima.StaticCode1");
  31.                 } catch (Exception e) {
  32.                         // TODO Auto-generated catch block
  33.                         e.printStackTrace();
  34.                 }
  35.                
  36.                 //new StaticCode1();
  37.                 //new StaticTest();
  38.         }
  39.        
  40. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
HM汪磊 + 1

查看全部评分

回复 使用道具 举报
Miss小强 发表于 2013-4-29 18:49
按我的理解应该没有错啊。
在创建实例对象,即new的时候执行构造代码块,他优先于任何构造函数。因此没new ...

StaticCode code=null这个确实没有加载类,之前是我弄错了。
现在的问题是老师的课件说静态代码块是第一个实例对象被创建时执行,如果老师的是正确的,那么StaticCodeDemo的静态代码块执行了也就是创建了第一个实例对象,既然创建了实例对象那么非静态代码块就应该也执行。但是实际运行结果是静态代码块执行了而非静态代码块没有执行。
这样视乎是老师的错了,而老师又从字节码上解析了他的观点。
两者矛盾,所以纠结在这呢。
回复 使用道具 举报
丘凤光 发表于 2013-4-30 01:20
StaticCode code=null这个确实没有加载类,之前是我弄错了。
现在的问题是老师的课件说静态代码块是第一 ...

程序运行结果说明了一切,相信结果吧。。。
回复 使用道具 举报
Sword 金牌黑马 2013-4-30 10:31:56
9#
同样没搞懂,坐等高手们解释
回复 使用道具 举报
Miss小强 发表于 2013-4-30 09:12
程序运行结果说明了一切,相信结果吧。。。

或许吧,要是没有更好的回答只能认为是老师很开心的笔误了:handshake
回复 使用道具 举报
静态代码是在当前类被调用的时候,才初始化的。
回复 使用道具 举报
看结果又什么疑问吗?我说下这个执行的顺序,你参考下
当你执行java StaticCodeDemo时,这个类被加载到内存中,按顺序执行Static{}中的代码->
然后执行main方法->接着你建立两个StaticCode对象,此时
StaticCode类的static{}在第一次对象被创建时执行,以后不再执行,{}中的代码每建立一个对象,执行一次
接着你又创建了 StaticCodeDemo对象,所以接着执行这个{}中的代码->,最后执行剩下的语句.

所以你去掉new  StaticCodeDemo()只是少了 System.out.println("StaticCodeDemo代码块"); 这个结果

你这个实验没有加构造函数.如果有的话,构造函数是排在{}代码块之后的,相当于每个对象共同操作.



回复 使用道具 举报


我是想知道静态代码块到底是随着类的加载而执行还是创建了第一个实例对象时执行。
_
回复 使用道具 举报
孙胜 发表于 2013-5-1 10:44
看结果又什么疑问吗?我说下这个执行的顺序,你参考下
当你执行java StaticCodeDemo时,这个类被加载到内存中, ...



我是想知道静态代码块到底是随着类的加载而执行还是创建了第一个实例对象时执行。
回复 使用道具 举报
突然想到一个更能说明问题的代码;
//这是静态代码块一,这个是类加载的动作吧
Class className=Class.forName("cn.itcast.problem.StaticCode1");
//这是实力化对象的动作吧
className。newInstance();
然后在看打印结果。这样应该清楚了。。。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马