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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 丘凤光 金牌黑马   /  2013-4-19 22:18  /  3872 人查看  /  19 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 丘凤光 于 2013-4-19 23:04 编辑

先声明,老鸟赶紧飘过~~
在论坛上搜索了一下静态代码块,发现很多人在帮别人解答的时候也给出了错误的答案。
一些知识不太扎实的人(我今天之前也是理解错误),认为静态代码块是随着类的加载而加载。
这是错误的。请看下面的测试程序
  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.                 //StaticCode1类已经加载,但是代码块却没有运行;
  41.                 StaticCode1 code1=null;
  42.                 StaticCode1 code12;

  43.                 System.out.println("over");
  44.         }
  45.         static
  46.         {
  47.                 System.out.println("StaticCodeDemo静态代码块2");
  48.         }
  49. }
复制代码
运行的结果为(有图有真相)

游客,如果您要查看本帖隐藏内容请回复

上面的测试代码也说明了程序的运行是:先创建main函数所在类的对象然后才找到main函数执行。

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1 神马都是浮云

查看全部评分

19 个回复

倒序浏览
嗯 解释的很好 顶一个
回复 使用道具 举报
你好,分享下
            static{
                  静态代码块中的执行语句
            }
        特点:随着类的加载而执行,只执行一次并优先于主函数。 用于给类进行初始化。
Persong   p  = new  Person("XX",XX);
这句话执行了:
   <1> 因为new用到了Person.class,所以会先找到Persong.class文件并加载到内存中
   <2> 执行该类中的static代码块,如果有的话,给Person.class类进行初始化
   <3> 在堆内存中开辟空间,分配内存地址
   <4> 在堆内存中建立对象特有属性,并进行默认初始化
   <5> 对属性进行初始化
   <6> 对对象进行构造代码块初始化
   <7> 对对象进行对应的构造函数初始化
   <8> 将内存地址赋给栈内存中的p变量
这就是一个很好的实现过程,画图会清晰的看到每一步.....

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
来看看是怎么回事。
回复 使用道具 举报
smile_joe 发表于 2013-4-19 22:56
你好,分享下
            static{
                  静态代码块中的执行语句

你说的这些步骤都正确,但是好像没有证明你说的
随着类的加载而执行
没有代码,没有运行结果图,你这样的说法很空洞
回复 使用道具 举报
隐藏的是什么好东东啊
回复 使用道具 举报
正是我问的问题,讲的很透彻,{:soso_e152:}
回复 使用道具 举报
本帖最后由 明锦添 于 2013-4-20 11:17 编辑

/*

需求:测试构造代码块、静态构造代码块的执行顺序。

*/

class StaticCode1

{

        static

        {

                System.out.println("StaticCode1——————静态代码块");
        }

        {

                System.out.println("StaticCode1————————代码块");
        }

}

class StaticCode

{

        static

        {

                System.out.println("StaticCode静态代码块——————");
        }

        {

                System.out.println("StaticCode代码块————————");
        }

}

class StaticCodeDemo

{

        static

        {

                System.out.println("StaticCodeDemo静态代码块1");
        }

        {

                System.out.println("StaticCodeDemo代码块");
        }

        public static void main(String[] args)
        {

                //连续创建两个StaticCode类的对象,静态代码块之执行一次,非静态代码块执行两次

                new StaticCode();

                new StaticCode();

                //同一个类中有多个静态代码块,按由上到下顺序执行

                new StaticCodeDemo();

                //StaticCode1类已经加载,但是代码块却没有运行;

                StaticCode1 code1=null;

                StaticCode1 code12;

                System.out.println("over");
        }

        static

        {

                System.out.println("StaticCodeDemo静态代码块2");
        }

}

我帮你分析一下:在主函数执行前要先加载主函数所在的类,在主函数所在类加载的同时,该类的
的静态代码块就会从上往下执行一次,输出的是System.out.println("StaticCodeDemo静态代码块1");
和System.out.println("StaticCodeDemo静态代码块2"); 在执行主函数的时候,因为 new StaticCode();
有两次,所以会先输出System.out.println("StaticCode静态代码块——————");一 次(在同一个函数中
多次建立同一个对象,该对象的静态代码块只执行一次),输出System.out.println("StaticCode代码块————————");
两次,执行到new StaticCodeDemo();时,本类对象的静态代码已经执行过一次这里不会再执行,而执行的是构造
代码块,输出的是System.out.println("StaticCodeDemo代码块");执行到StaticCode1 code1=null;和StaticCode1 code12;时
因为没有建立对象,所以没有任何输出,最后执行System.out.println("over"); 所以你看到的结果就是
StaticCodeDemo静态代码块1
StaticCodeDemo静态代码块2
StaticCode静态代码块——————
StaticCode代码块————————
StaticCode代码块————————
StaticCodeDemo代码块
over

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
我来凑个热闹,从未隐藏的代码来看,个人觉得不能说明你所说明的问题。
//StaticCode1类已经加载,但是代码块却没有运行;
                StaticCode1 code1=null;
                StaticCode1 code12;
这里没有创建任何对象,从设计的合理性来猜测,StaticCode1 code1=null;
                和StaticCode1 code12,既然没有创建对象,就没有必要加载类。
除非有其它的证据说明,这里类已经被加载。
    以上只是合理性猜测,如果你有更好的证据。

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
补充下:   你只要把第四十三行注释掉,看看运行结果。就发现,这个结论是错误的:先创建main函数所在类的对象然后才找到main函数执行
好了,先说明,我不是要故意来找茬哈,只是对这些特别的地方特别感兴趣,想弄清楚究竟。
回复 使用道具 举报
看看!学习!!
回复 使用道具 举报
静态代码块不是在类加载时被调用的,而是第一个实例对象被创建时才执行的。

我的理解---
创建实例对象,要加载类!应该是先加载类,同时静态代码块被调用;
  1. class StaticCode{
  2.          static
  3.      {
  4.              System.out.println("StaticCode静态代码块——————");
  5.      }
  6.      {
  7.              System.out.println("StaticCode代码块————————");
  8.      }
  9. }

  10. class StaticCode1 extends StaticCode
  11. {
  12.         static
  13.         {
  14.                 System.out.println("StaticCode1——————静态代码块");
  15.         }
  16.         {
  17.                 System.out.println("StaticCode1——————代码块");
  18.         }
  19. }

  20. public class Test {
  21.         public static void main(String[] args){
  22.                 StaticCode1 code1 = new StaticCode1();//创建StaticCode1的实例,但会加载器父类
  23.                 System.out.println("over");
  24.         }
  25. }
复制代码
结论:静态代码块是随着类的加载而加载

捕获.PNG (8.77 KB, 下载次数: 24)

捕获.PNG

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
陈山洪 来自手机 高级黑马 2013-4-20 18:27:03
13#
我只是想看隐藏文件来自: Android客户端
回复 使用道具 举报
黑马伍哲沂 发表于 2013-4-20 11:42
补充下:   你只要把第四十三行注释掉,看看运行结果。就发现,这个结论是错误的:先创建main函数所在类的 ...

很高兴你提出不同的见解:handshake
张孝祥老师是从字节码上解析的,建议你看一下张老师的基础加强1
回复 使用道具 举报
黑马伍哲沂 发表于 2013-4-20 11:42
补充下:   你只要把第四十三行注释掉,看看运行结果。就发现,这个结论是错误的:先创建main函数所在类的 ...

很高兴你提出不同的观点,对不起,因为我没有提前说明,我的意思:先创建main函数所在类的对象然后才找到main函数执行  我是说隐式创建(这点我忘了提前说明了)
43行的代码 我只是想证明一个类中有多个静态代码块时是按由上到下执行的  不是为了证明你说的这一点的。

你可以用代码从字节码上分析一下。建议你回看一下张老师的基础加强1。
回复 使用道具 举报
黑马伍哲沂 发表于 2013-4-20 11:42
补充下:   你只要把第四十三行注释掉,看看运行结果。就发现,这个结论是错误的:先创建main函数所在类的 ...

很高兴你提出不同的观点,对不起,因为我没有提前说明,我的意思:先创建main函数所在类的对象然后才找到main函数执行  我是说隐式创建(这点我忘了提前说明了)
43行的代码 我只是想证明一个类中有多个静态代码块时是按由上到下执行的  不是为了证明你说的这一点的。

你可以用代码从字节码上分析一下。建议你回看一下张老师的基础加强1。
回复 使用道具 举报
丘凤光 发表于 2013-4-21 13:19
很高兴你提出不同的观点,对不起,因为我没有提前说明,我的意思:先创建main函数所在类的对象然后才找到 ...

嗯  我会看的。  还没看到张老师的加强部分。
但这里还是有个问题,从程序运行的结果来看,如果把43行注释掉,虽然主函数中静态代码块会被执行。、
但我发现构造代码块却没有执行。  只有43行没被注释才会执行。
如果这个疑问能从张老师的视频里得到解答,就不用回复我了。也许我看到那里才能理解。
回复 使用道具 举报
看看隐藏的再来 讨论。
回复 使用道具 举报
黑马伍哲沂 发表于 2013-4-21 14:10
嗯  我会看的。  还没看到张老师的加强部分。
但这里还是有个问题,从程序运行的结果来看,如果把43行注 ...

嗯,你这个问题我没考虑到。要是这样的话,这和张老师的就矛盾了……
看来得请教真正的大神了。
回复 使用道具 举报
楼主的代码中,46,47行并没有加载类
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马