Java误区: 静态代码块,会在类被加载时自动执行?

JAVA静态代码块会在类被加载时自动执行?

        很多Java开发者的思想,被这个思想深深的轮奸了n遍,传播这个错误思想的博客,在网上一堆,越来越多的人被轮奸。

        如:http://blog.csdn.net/leeyu35/article/details/7755304


那么我们程序来证明这句话是错误的:

class MyClass1 {
	static {//静态块
		System.out.println("static block ");
	}
}
public class Main {

	Class[] classArray = {
			MyClass1.class//这样引用该类,必然需要将该类加载到虚拟机中
	};
	public static void main(String[] args){
		System.out.println("hello word");
	}

}

执行结果:并没有输出" static bolck"


那么什么时候才会调用静态块呢?我找到一篇,介绍比较详细的博客。

http://www.cnblogs.com/ivanfu/archive/2012/02/12/2347817.html


↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 以上发表于2014-10-16 20:13 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑






↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 以下更新于:2017-07-24 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

关于 《Java误区: 静态代码块,会在类被加载时自动执行?》 回复与更新


1.道歉:

首先,我承认,上面的demo犯了一个严重的低级的错误,Main的成员classArray并不会被赋值,因为系统并不会创建Main的对象。正确的写法应该是:

    static Class[] classArray = {
            MyClass1.class
    };  


2. 谢谢你们友善的提醒。

5楼:@Johnny_Xiu , 7楼:@jzb2008lds ,10楼:@深蓝水域 , 12楼:@asd1_123
你们的回复:“请删除本文,以防误导他人”。我看到了,很抱歉很久没有上csdn,这么晚才看到。
恩,谢谢你们友善的提醒。
但是,尼采说过:"生活不能逃避,只能勇敢面对"。
所以我不打算删帖逃避问题,那是懦夫才会做的事,我选择把问题解决。

demo和blog是2014-10-16写的;已经过去了3年,我也不记得当时为什么会犯这么一个错误,也许是粗心,也许是因为喝了点酒,谁知道呢……

但是,这篇blog要表达的观点一定是对的。


3.为了减少歧义,改进后的demo

package com.test;
import java.lang.Class;

class MyClass1 {  
    static {//静态块  
        System.out.println("static block ");  
    }  
}
public class Hello {
    public static void main(String[] args){  
        System.out.println("hello word: " + MyClass1.class);
    }  
}


输出结果(并没有输出 “static block”。)

Alt 输出结果


4. 为什么 “MyClass1.class” 这种方式,不会触发,MyClass1的静态代码块的执行?

Alt 类加载的5个阶段

如上图所示,静态代码块的执行是处在类加载的最后一个阶段“初始化”。参考oracle:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

那么什么时候会触发初始化阶段,请参考上述文档中的:5.5. Initialization

英语不太好的,搓这里 http://blog.csdn.net/xuefeng0707/article/details/9132339

根据上面文档,显然:MyClass1.class 这种使用方式,并不会触发,MyClass1类的初始化。所以并不会执行,MyClass1的静态代码块。


5.Class.forName()

    public static Class<?> forName(
        String name,
        //如果initialize = false,那么类会被加载,但不会执行静态代码块。
        boolean initialize,//whether the class must be initialized;
        ClassLoader loader
    )

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String,%20boolean,%20java.lang.ClassLoader)

3楼:@UltraNeo

你可能没有看到,当时blog末尾推荐的链接:
  http://www.cnblogs.com/ivanfu/archive/2012/02/12/2347817.html
  链接文中也讲解了Class.forName()方法.
首先你是对的:Class.forName("com.test.MyClass1");这样调用在加载过程会执行静态代码块。
但是:不代表所有的forName()方法的调用都会执行“静态代码块”。
如下并不会执行静态代码块:
   Class.forName("com.test.MyClass1",false,classLoader);


6. MyClass1.class的使用方式,会触发 MyClass1.class 加载到虚拟机的吗?

答案当然是肯定的:一定会加载到虚拟机。“并且他的Class对象存储在ClassLoader中”

6楼:@烁GG 

废话不多说,demo证明一切:

public class Main {

    public static void main(String[] args){
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        printClassesOfClassLoader(loader);
        System.out.println("-------------------- hello " + MyClass1.class + " --------------------");
        printClassesOfClassLoader(loader);

    }
    
    public static void printClassesOfClassLoader(ClassLoader loader){
        try {
            Field classesF = ClassLoader.class.getDeclaredField("classes");
            classesF.setAccessible(true);
            Vector<Class<?>> classes = (Vector<Class<?>>) classesF.get(loader);
            for(Class c : classes) {
                System.out.println(c);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}


输出结果:

Alt 输出结果



我当时为什么会写这篇blog?

这可能需要,讨论到另外一个知识点:《静态代码块是在主线程中执行吗?》
因为这个特性,android 5.0 之前的版本,提供的 AsyncTask 类 ,为我们android开发者留下了一个坑。
之后的版本修复了这个坑。

我不想展开来细说这个问题,因为:
  1. 这个问题与这篇blog的标题不符
  2. 不想把这篇blog的篇幅拉的很长,尽管已经很长了
  3. 并不知道大家对这个问题是否有兴趣,如果大家对这个问题有兴趣的话,给我留言,我看到有留言,我再来开一篇新的blog,专门来说清楚这个问题。



最后 4楼:@gate120

你说的很对,感谢你,顶着我的一片骂名道出真相。


猜你喜欢

转载自blog.csdn.net/jiese1990/article/details/40154329
今日推荐