静态块里的代码不一定是第一次被加载时执行,
确切的说应该是第一次实例化的时候执行~因为他的执行和类的加载方式有关:
看看下面的:
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()!从结果很明显看出:
静态块的执行是类第一次实例化的时候进行的~~~~~
而 不是 大家常说的第一次加载类的时候执行的!!!!!
确切地new指的是实例化一个对象,
并不是单纯加载~~单纯的加载指的就是由某一个classLoader将你的class载入内存的过程~
你要实例化一个类,就必须现加载这个类~加载的概念只有一个,没有ls所说的此呀彼呀的~
难道这点代码都看不懂吗!
代码上已经明确的说明了什么是加载,什么是实例化!!这个帖子不是讨论什么事实例化什么事加载!!
而是要说明一个事实:
static静态块
是在类第一次实例化的时候执行的;
而不是在类刚加载的时候执行的!
static{
System.out.println("执行静态块!");
Throwable t = new Throwable();
t.printStackTrace();
}
这种方式,这种方式更容易理解这些原因了:
原例子不变,改一下加载方式:^_^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的时候
^_^~~~
自己打自己的脸确切的说,是第一次初始化的时候执行,而不是第一次实例化的时候执行
比如一个你前面forName测试的例子,即使不实例化,还是会输出静态初始化块的运行结果
有没搞错
自己打自己的脸确切的说,是第一次初始化的时候执行,而不是第一次实例化的时候执行
比如一个你前面forName测试的例子,即使不实例化,还是会输出静态初始化块的运行结果
===============================================================================你是不是理解能力有限~~~
我前面已经明确告诉你了
我们经常用的Class.ForName(String className);
只有一个参数,此时它的第二个参数就是true,
第三个参数就是当前类的加载器,其实也就是appClassLoader~~
别老断章取义~~~
代码上已经很明白~
难道这点代码都看不懂吗!
代码上已经明确的说明了什么是加载,什么是实例化!!这个帖子不是讨论什么事实例化什么事加载!!
而是要说明一个事实:
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类实例化吧。
类加载
类初始化 <-- 这里会执行静态初始化代码
实例化这样是不是清楚一点了 ;->
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();
}
}
只要你看一下运行结果就可以证明你的以下观点:
=====================================
静态块里的代码不一定是第一次被加载时执行,
确切的说应该是第一次实例化的时候执行~
===================================
是错误的
支持楼主!帮楼主找到了一个理论依据:在 Java Language Specification 中找到这样一句“Any static initializers declared in a class are executed when the class is initialized”,也就是说,并不是在“加载(loadClass)”的时候,而是在“initialized”的时候。至于什么时候是“initialized”,也不难找到,用如下代码就能清楚地看到了:
=============================================================================楼主说的是“实例化”,而不是initialized,
“实例化”与class is initialized是两回事。
然后再来好好总结一下。
>“实例化”与class is initialized是两回事。不错,我发帖子说“支持楼主”的时候,只是通过 (new Throwable()).printStackTrace() 的方式看到执行静态初始化代码的时候确实是在 newInstance() 的过程中,当时我也没分清“实例化”和“initialized”。现在看起来,“类加载”、“类初始化”和“实例化”是三个不同的过程,其中“类初始化”从表现上一般跟“实例化”是一起的,但也有可能是分离的。不可否认,楼主提出了一个我们往往忽略的细节。对这个细节的掌握虽然无助于日常的 coding 工作,但适当地思考一下此类问题,对于深入理解一门语言是有帮助的。我喜欢这样的问题,感谢楼主 :)
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块的代码的,
但是你们测试了把这段代码放到后面执行的结果了吗!?
不排除大多数是新手~~有的人只知道书上写的,从不动手去写,但他们哪里知道书上的并不都是对的~~
遇到问题自己去写出来,用事实证明这才是道理!!~
不管对错,能拿出例子来,不能只凭一句xxxx书上写的清楚~~拿程序来说话才是做程序员的素质要求!