静态块里的代码不一定是第一次被加载时执行,
确切的说应该是第一次实例化的时候执行~因为他的执行和类的加载方式有关:
看看下面的:
1,测试类:
package com.daniel.test;public class TestStatic {
  static{
    System.out.println("执行静态块!");
  }
  public void print(){
    System.out.println("执行TestStatic.print()!");
  }
}
2,主类:
package com.daniel.test;
public class StaticTest {
  public static void main(String[] args) throws Exception {
    StaticTest st = new StaticTest();
    System.out.println("准备加载com.daniel.test.TestStatic...");
    Class clazz = st.getClass().getClassLoader().loadClass("com.daniel.test.TestStatic");
    System.out.println("加载com.daniel.test.TestStatic成功!");
    System.out.println("准备实例化com.daniel.test.TestStatic...");
    TestStatic ts = (TestStatic)clazz.newInstance();
    System.out.println("实例化com.daniel.test.TestStatic成功!");
    ts.print();
  }
}3,执行结果:
准备加载com.daniel.test.TestStatic...
加载com.daniel.test.TestStatic成功!
准备实例化com.daniel.test.TestStatic...
执行静态块!
实例化com.daniel.test.TestStatic成功!
执行TestStatic.print()!从结果很明显看出:
静态块的执行是类第一次实例化的时候进行的~~~~~
而 不是 大家常说的第一次加载类的时候执行的!!!!!

解决方案 »

  1.   

    ls的是不是指的new~
    确切地new指的是实例化一个对象,
    并不是单纯加载~~单纯的加载指的就是由某一个classLoader将你的class载入内存的过程~
    你要实例化一个类,就必须现加载这个类~加载的概念只有一个,没有ls所说的此呀彼呀的~
      

  2.   

    代码上已经很明白~
    难道这点代码都看不懂吗!
    代码上已经明确的说明了什么是加载,什么是实例化!!这个帖子不是讨论什么事实例化什么事加载!!
    而是要说明一个事实:
    static静态块
    是在类第一次实例化的时候执行的;
    而不是在类刚加载的时候执行的!
      

  3.   

    支持楼主!帮楼主找到了一个理论依据:在 Java Language Specification 中找到这样一句“Any static initializers declared in a class are executed when the class is initialized”,也就是说,并不是在“加载(loadClass)”的时候,而是在“initialized”的时候。至于什么时候是“initialized”,也不难找到,用如下代码就能清楚地看到了:
      static{
        System.out.println("执行静态块!");
        Throwable t = new Throwable();
        t.printStackTrace();
      }
      

  4.   

    实例化跟加载功能上并不一样,虽然大多数的Java虚拟机采用的lazy loading的方式,也就是当一个类第一次需要被实例化的时候才会从磁盘读取byte code加载类,不过这不是必然,有时候为了特殊原因,比如加密或者完整性检查,可以先加载所有用到的类,然后慢慢实例化,或者Java虚拟机直接就这么做了。楼主共享的经验,不顶是不行的。
      

  5.   

    类的加载还有一种方式,Class.forName()
    这种方式,这种方式更容易理解这些原因了:
    原例子不变,改一下加载方式:^_^public static void main(String[] args) throws Exception {
      StaticTest st = new StaticTest();
      System.out.println("准备加载test.TestStatic...");
      Class clazz = Class.forName("test.TestStatic", true, st.getClass() .getClassLoader());
      System.out.println("加载test.TestStatic成功!");
      System.out.println("准备实例化test.TestStatic...");
      TestStatic ts = (TestStatic) clazz.newInstance();
      System.out.println("实例化test.TestStatic成功!");
      ts.print();
    }注意一下:
    Class clazz = Class.forName("test.TestStatic", true, st.getClass() .getClassLoader());
    的第二个参数,现在是true,执行的结果是:
    准备加载test.TestStatic...
    执行静态块!
    加载test.TestStatic成功!
    准备实例化test.TestStatic...
    实例化test.TestStatic成功!
    执行TestStatic.print()!下面我们改成false:
    Class clazz = Class.forName("test.TestStatic", false, st.getClass() .getClassLoader());
    输出结果:
    准备加载test.TestStatic...
    加载test.TestStatic成功!
    准备实例化test.TestStatic...
    执行静态块!
    实例化test.TestStatic成功!
    执行TestStatic.print()!^_^
    static的执行顺序变了吧~~~~~~其实,我们经常用的Class.ForName(String className);
    只有一个参数,此时它的第二个参数就是true,
    第三个参数就是当前类的加载器,其实也就是appClassLoader~~所以说,static静态块的执行只能是“确切地说”
    在“类第一次实例化的时候执行”~~~
    其使我们也能控制它在加载(load)的时候执行,比如false的时候
    ^_^~~~
      

  6.   

    有没搞错
    自己打自己的脸确切的说,是第一次初始化的时候执行,而不是第一次实例化的时候执行
    比如一个你前面forName测试的例子,即使不实例化,还是会输出静态初始化块的运行结果
      

  7.   

    redduke1202(勿以分少而不回★★勿以分多而灌水) ( ) 信誉:100    Blog   加为好友  2007-04-20 13:14:10  得分: 0  
     
     
       有没搞错
    自己打自己的脸确切的说,是第一次初始化的时候执行,而不是第一次实例化的时候执行
    比如一个你前面forName测试的例子,即使不实例化,还是会输出静态初始化块的运行结果
      
     ===============================================================================你是不是理解能力有限~~~
    我前面已经明确告诉你了
    我们经常用的Class.ForName(String className);
    只有一个参数,此时它的第二个参数就是true,
    第三个参数就是当前类的加载器,其实也就是appClassLoader~~
    别老断章取义~~~
      

  8.   

    daniel_kaka() ( ) 信誉:100    Blog   加为好友  2007-4-20 0:07:43  得分: 0  
     
     
       
    代码上已经很明白~
    难道这点代码都看不懂吗!
    代码上已经明确的说明了什么是加载,什么是实例化!!这个帖子不是讨论什么事实例化什么事加载!!
    而是要说明一个事实:
    static静态块
    是在类第一次实例化的时候执行的;
    而不是在类刚加载的时候执行的!  
    看到这我只想举个例子出来说明一下,即类的静态块不是在类被第一次实例化时才执行的 class Test {
    static int a=0;
      static {
        System.out.println("ABC");
      }
       Test() {
            System.out.println(a + " } ");
       }
    }
     public class Ttest{
    public static void main(String args[]) {
    Test.a=10;
    } }
    结果是
    ABC
    我想已经很明白了吧,这个例子里面并没有把Test类实例化吧。
      

  9.   

    hehe, 现在已经有三个概念了:
       类加载
       类初始化  <-- 这里会执行静态初始化代码
       实例化这样是不是清楚一点了  ;->
      

  10.   

    楼主的观点充满了错误:把你的代码稍改一下:
    package com.daniel.test;public class TestStatic {
      static{
        System.out.println("执行静态块!");
      }
      public void print(){
        System.out.println("执行TestStatic.print()!");
      }  //这是我加的
      public static void printStatic(){
        System.out.println("执行TestStatic.printStatic()!");
      }
    }
    2,主类:
    package com.daniel.test;
    public class StaticTest {
      public static void main(String[] args) throws Exception {
    TestStatic.printStatic();//这是我加的    StaticTest st = new StaticTest();
        System.out.println("准备加载com.daniel.test.TestStatic...");
        Class clazz = st.getClass().getClassLoader().loadClass("com.daniel.test.TestStatic");
        System.out.println("加载com.daniel.test.TestStatic成功!");
        System.out.println("准备实例化com.daniel.test.TestStatic...");
        TestStatic ts = (TestStatic)clazz.newInstance();
        System.out.println("实例化com.daniel.test.TestStatic成功!");
        ts.print();
      }
    }
    只要你看一下运行结果就可以证明你的以下观点:
    =====================================
    静态块里的代码不一定是第一次被加载时执行,
    确切的说应该是第一次实例化的时候执行~
    ===================================
    是错误的
      

  11.   

    =============================================================================
    支持楼主!帮楼主找到了一个理论依据:在 Java Language Specification 中找到这样一句“Any static initializers declared in a class are executed when the class is initialized”,也就是说,并不是在“加载(loadClass)”的时候,而是在“initialized”的时候。至于什么时候是“initialized”,也不难找到,用如下代码就能清楚地看到了:
    =============================================================================楼主说的是“实例化”,而不是initialized,
    “实例化”与class is initialized是两回事。
      

  12.   

    强烈建议楼主把<<深入JAVA虚拟机>>买回来,好好看看“第7章 类型的生命周期”,
    然后再来好好总结一下。
      

  13.   

    static块会在第一次生成实例或者第一次调用类的静态变量或者静态函数的时候运行,而这两种情况都需要装载类,可以近似的认为static块是在装载类的时候运行。lz的例子只不过是通过自己加载来说明执行static块是在生成实例之前而不是之后,但lz却忽略了不生成实例而直接调用类的静态成员的情况,楼上的几位也提到了这一点。没有经过全面的测试而得出的这个结论并不是完全正确。
      

  14.   

    > 楼主说的是“实例化”,而不是initialized,
    >“实例化”与class is initialized是两回事。不错,我发帖子说“支持楼主”的时候,只是通过 (new Throwable()).printStackTrace() 的方式看到执行静态初始化代码的时候确实是在 newInstance() 的过程中,当时我也没分清“实例化”和“initialized”。现在看起来,“类加载”、“类初始化”和“实例化”是三个不同的过程,其中“类初始化”从表现上一般跟“实例化”是一起的,但也有可能是分离的。不可否认,楼主提出了一个我们往往忽略的细节。对这个细节的掌握虽然无助于日常的 coding 工作,但适当地思考一下此类问题,对于深入理解一门语言是有帮助的。我喜欢这样的问题,感谢楼主  :)
      

  15.   

    to :   KRplusSRequalGOD(狂人+善人=神) ( ) 信誉:100  2,主类:
    package com.daniel.test;
    public class StaticTest {
      public static void main(String[] args) throws Exception {    StaticTest st = new StaticTest();
        System.out.println("准备加载com.daniel.test.TestStatic...");
        Class clazz = st.getClass().getClassLoader().loadClass("com.daniel.test.TestStatic");
        System.out.println("加载com.daniel.test.TestStatic成功!");
        System.out.println("准备实例化com.daniel.test.TestStatic...");
        TestStatic ts = (TestStatic)clazz.newInstance();
        System.out.println("实例化com.daniel.test.TestStatic成功!");
        ts.print();
        TestStatic.printStatic();//这是我加的
      }
    }试试上面代码~~~
    你是人为的把TestStatic.printStatic(),提到前面执行,
    你如果把它写到后面呢,你可以自己看看结果~
    即过很明显,static块仍就不是先执行的~~
    你的说法不正确呀~~~
    因为按照你的说法,
    TestStatic.printStatic()不管放到哪,static都要先执行才对!另外还有用
    public static int a=10;
    这一类的来说明load class的时候就执行静态块,
    但你们用的例子也是把System.out.println(StaticTest.a);
    放到load class的前面执行的,犯了上面同样的错误!按照你们的说法,System.out.println(StaticTest.a);
    不管放到那都要先执行static块的代码的,
    但是你们测试了把这段代码放到后面执行的结果了吗!?
      

  16.   

    不过也该结贴了~~~从这些可以看出来,一些人的认识实在是太肤浅了~~~
    不排除大多数是新手~~有的人只知道书上写的,从不动手去写,但他们哪里知道书上的并不都是对的~~
    遇到问题自己去写出来,用事实证明这才是道理!!~
    不管对错,能拿出例子来,不能只凭一句xxxx书上写的清楚~~拿程序来说话才是做程序员的素质要求!