static块到底什么时候执行?(转自javaeye上面的讨论) - 花非花 - CSDNBlog
来源:百度文库 编辑:神马文学网 时间:2024/04/30 06:12:45
"java深度历险"一书在讲解“类装载”的一章中,举了以下的例子:
引用:
java代码:
public interface Assembly{
public void start();
}
public class Word implements Assembly{
static{
System.out.println("Word static initialization!");
}
public void start(){
System.out.prinlnt("Word starts");
}
}
public class Office{
public static void main(String args[]) throws Exception{
Office off = new Office();
System.out.println("类别准备载入");
Class c = Class.forName(args[0],true,off.getClass().getClassLoader());
System.out.println("类别准备实例化");
Object o = c.newInstance();
Object o2= c.newInstance();
}
}
执行java Office Word,运行结果如下:
“Loaded Office”
“类别准备载入”
“Loaded Accembly”
“Loaded Word””
“Word static initialization”
“类别准备实体化”。
但是如果将Office.java中Class.forName(args[0],true,off.getClass().getClassLoader())中的true变为false,再执行java Office Word结果显示为:
“Loaded Office”
“类别准备载入”
“Loaded Accembly”
“Loaded Word””
“类别准备实体化”
“Word static initialization”。
显然两次红字部分顺序相反,及static块执行的顺序不同。此书作者提出了原因,原文: 引用: “过 去很多java书上提到静态初始化(static initializion block)时,都会说静态初始化区块只是在类第一次载入的时候才会被调用仅仅一次。可是上面输出却发现即使类被载入了,其静态初始化区块也没有被调用, 而是在第一次调用newInstance方法时,静态初始化块才被真正调用,应该改成-静态初始化块只是在类被第一次实体化的时候才会被仅仅调用一次。”
其实,该书作者的上述描述有误。通过一个试验,就可以看出谬误所在。
java代码:
public class TestA{
static{
System.out.println("Static block executed!");
}
}
public class Test{
public static void main(String args[]){
Test test = new Test();
Class.forName("TestA",true,test.getClass().getClassLoader());
}
}
运行一下,相信大家一定可以看到,“Static block executed!”的输出。这与 引用: 而是在第一次调用newInstance方法时,静态初始化块才被真正调用 的说法矛盾。
其实我想事实是这样的:
一个类的运行,JVM做会以下几件事情 1、类装载 2、链接 3、初始化4、实例化;而初始化阶段做的事情是初始化静态变量和执行静态方法等的工作。所以,当Class.forName(args[0],true,off.getClass().getClassLoader());中的true变为false的时候,就是告诉JVM不需再loadclass之后进行initial的工作。这样,将initial的工作推迟到了newInstance的时候进行。所以,static块的绝对不是什么“只是在类被第一次实体化的时候才会被仅仅调用一次”,而应该是在类被初始化的时候,仅仅调用一次。
[收藏到我的网摘] Denny发表于 2006年03月29日 21:21:00
引用:
java代码:
public interface Assembly{
public void start();
}
public class Word implements Assembly{
static{
System.out.println("Word static initialization!");
}
public void start(){
System.out.prinlnt("Word starts");
}
}
public class Office{
public static void main(String args[]) throws Exception{
Office off = new Office();
System.out.println("类别准备载入");
Class c = Class.forName(args[0],true,off.getClass().getClassLoader());
System.out.println("类别准备实例化");
Object o = c.newInstance();
Object o2= c.newInstance();
}
}
执行java Office Word,运行结果如下:
“Loaded Office”
“类别准备载入”
“Loaded Accembly”
“Loaded Word””
“Word static initialization”
“类别准备实体化”。
但是如果将Office.java中Class.forName(args[0],true,off.getClass().getClassLoader())中的true变为false,再执行java Office Word结果显示为:
“Loaded Office”
“类别准备载入”
“Loaded Accembly”
“Loaded Word””
“类别准备实体化”
“Word static initialization”。
显然两次红字部分顺序相反,及static块执行的顺序不同。此书作者提出了原因,原文: 引用: “过 去很多java书上提到静态初始化(static initializion block)时,都会说静态初始化区块只是在类第一次载入的时候才会被调用仅仅一次。可是上面输出却发现即使类被载入了,其静态初始化区块也没有被调用, 而是在第一次调用newInstance方法时,静态初始化块才被真正调用,应该改成-静态初始化块只是在类被第一次实体化的时候才会被仅仅调用一次。”
其实,该书作者的上述描述有误。通过一个试验,就可以看出谬误所在。
java代码:
public class TestA{
static{
System.out.println("Static block executed!");
}
}
public class Test{
public static void main(String args[]){
Test test = new Test();
Class.forName("TestA",true,test.getClass().getClassLoader());
}
}
运行一下,相信大家一定可以看到,“Static block executed!”的输出。这与 引用: 而是在第一次调用newInstance方法时,静态初始化块才被真正调用 的说法矛盾。
其实我想事实是这样的:
一个类的运行,JVM做会以下几件事情 1、类装载 2、链接 3、初始化4、实例化;而初始化阶段做的事情是初始化静态变量和执行静态方法等的工作。所以,当Class.forName(args[0],true,off.getClass().getClassLoader());中的true变为false的时候,就是告诉JVM不需再loadclass之后进行initial的工作。这样,将initial的工作推迟到了newInstance的时候进行。所以,static块的绝对不是什么“只是在类被第一次实体化的时候才会被仅仅调用一次”,而应该是在类被初始化的时候,仅仅调用一次。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=643630
[收藏到我的网摘] Denny发表于 2006年03月29日 21:21:00
static块到底什么时候执行?(转自javaeye上面的讨论) - 花非花 - CSDNBlog
c# static的全部用法 - acefly的专栏 - CSDNBlog
网友讨论:ERP实施未来展望 - Drate的随笔 - CSDNBlog
C++的static关键字
C++的static关键字
C++的static关键字
华尔街日报:中国的房价到底什么时候掉下来?
java中static的作用
C++的static关键字1
C#中static的使用
c# static的全部用法
JAVA中static的作用
关于REST的一点想法,欢迎大家讨论。-rails-Ruby -JavaEye做最棒的软件...
Spring书籍-Spring-入门讨论 -JavaEye做最棒的软件开发交流社区
关于REST的一点想法,欢迎大家讨论。 - rails - Ruby - JavaEye论...
标语上面的箭头
人民币上面的人
讨论:Web2.0到底是他妈的什么东西?
太经典了,不转不行淘宝上面的对话
太经典了,不转不行淘宝上面的对话
对于树状结构数据的缓存设计方案的讨论-企业应用-Java -JavaEye做最棒的软件开发...
c语言static与extern的用法
Java关键字final, static的用法总结
关于《如何塑造自己成为一名合格的软件工程师》的讨论 - 求职宝典 - JavaEye专栏频...