java类加载中不会触发初始化的被动引用

标签: java 加载 初始化 | 发表时间:2014-09-02 21:05 | 作者:得小白者天下得
出处:http://www.iteye.com
我们知道,在初始化一个类时,如果它的父类没有进行初始化,那么JVM就会触发其父类的初始化动作。但是,当我们引用类的时候,可不一定会触发其初始化,这种引用类的方式称为被动引用。
看下面的例子:
public class NotInit {
	public static void main(String[] args) {
		System.out.println(Child.val);
//		System.out.println(Father.str);
		Father[] father = new Father[4];
		System.out.println(Constant.HELLO);
	}

}


class Father {
	static {
		System.out.println("Father init!");
	}
	
	public static int val = 100;
//	public static String str = "string";
}

class Child extends Father {
	static {
		System.out.println("Child init!");
	}
}

class Constant {
	static {
		System.out.println("Constant init");
	}
	
	public static final String HELLO = "HELLO";
}

见证奇迹的时刻到了!!!程序输出为:
Father init!
100
HELLO


这不科学啊!!!代码中调用了
System.out.println(Child.val);

可是没有竟然没有对Child类进行初始化。这是因为val为静态字段,只有直接定义这个字段的类才会被初始化,故通过子类来引用父类静态字段val,只会触发Father类的初始化,而不会触发Child类的初始化,so 就没有Child类的事。
再来,代码中虽然有
Father[] father = new Father[4];

可是Father类居然没有初始化,这也是情理之中的。这句代码仅仅定义了一个Father类型的一维数组,数组里面什么都没有放!就好比我买了一个可以容纳100L的容器,而且是只能用来装浓硫酸的容器,但是我现在还没把浓硫酸放入容器,所以容器中什么也没有,即是没有初始化。
看官接着往下瞧:
System.out.println(Constant.HELLO);

Constant类没有直接父类,可为何还是没能初始化Constant类。大家也看见了,HELLO是一个常量。常量和一般的变量不一样,因为HELLO是常量,所以Constant类在编译阶段通过常量优化传播,把HELLO所代表的"hello"存储到了NotInit类的常量池中。说人话就是,以后NotInit类对常量Constant.HELLO的引用实际都转化为NotInit类对自身常量池的引用了。在编译结束后,Constant类和NotInit类就劳燕分飞各自走了。

总结是个好习惯!本文描述了类加载过程中的三种被动引用,这些情况下都不会触发相应类的初始化:
一、 通过子类引用父类的静态字段,不会导致子类初始化
二、 通过数组定义来引用类,不会触发该类的初始化
三、 常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的那个类,所以也不会触发定义常量的类的初始化

已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java 加载 初始化] 推荐:

java类加载中不会触发初始化的被动引用

- - Java - 编程语言 - ITeye博客
我们知道,在初始化一个类时,如果它的父类没有进行初始化,那么JVM就会触发其父类的初始化动作. 但是,当我们引用类的时候,可不一定会触发其初始化,这种引用类的方式称为被动引用. 可是没有竟然没有对Child类进行初始化. 这是因为val为静态字段,只有直接定义这个字段的类才会被初始化,故通过子类来引用父类静态字段val,只会触发Father类的初始化,而不会触发Child类的初始化,so 就没有Child类的事.

Java 类初始化顺序

- - Java - 编程语言 - ITeye博客
  对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是. 1.(静态变量、静态初始化块)注:这两个的初始化顺序为在类中先后出现的顺序. 2(变量、初始化块)注:这两个的初始化顺序为在类中先后出现的顺序.  我们也可以通过下面的测试代码来验证这一点:. public static String staticField = "静态变量";.

java 类和对象的初始化

- - Web前端 - ITeye博客
  在Java中,类装载器把java类装载到虚拟机中,经过装载,链接和初始化三个步骤来完成. 其中链接中包括 校验、准备和解析. 下面对这些概念进行解析:. 装载:查找和导入类或接口的二进制数据,常用的是根据类的路径加载,还有根据网络的地址加载. 链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的;.

java动态加载

- - Java - 编程语言 - ITeye博客
第一部分:Java虚拟机启动时,关于类加载方面的一些动作. 当使用java ProgramName.class运行程序时,Java找到JRE,接着找到jvm.dll,把该动态库载入内存,这就是JVM. 然后加载其它动态库, 并激活JVM. JVM激活之后会进行一些初始化工作,之后生成BootstrapLoader,该Class Loader是由C++写的.

java中一个对象的初始化过程

- - CSDN博客编程语言推荐文章
/* 该类演示了一个对象的初始化过程 */ class Person {. //堆内存默认初始化为null. private static String country="中国"; //静态属性,存在于方法区,随着类的加载而加载. System.out.println("静态代码块执行");. System.out.println("构造代码块执行");.

来说说Java中的实例初始化器

- - ImportNew
文首先给出个例子来探究下什么是 实例变量初始化器,什么是 实例初始化器,以及什么是 静态初始化器. 然后看看实例初始化器是怎么工作的. 先看看下面这段代码,你觉着哪部分会先被执行呢. //instance variable initializer 实例变量初始化器. //constructor 构造函数.

类在什么时候加载和初始化

- - Java - 编程语言 - ITeye博客
理解类在JVM中什么时候被加载和初始化是Java编程语言中的基础概念,正因为有了Java语言规范,我们才可以清晰的记录和解释这个问题,但是很多Java程序员仍然不知道什么时候类被加载,什么时候类被初始化,类加载和初始化好像让人很困惑,对初学者难以理解,在这篇教程中我们将看看类加载什么时候发生,类和接口是如何被初始化的,我并不会拘泥于类加载器的细节或者说类加载器的工作方式.

Java资源加载详解

- - 企业架构 - ITeye博客
Java开发中常常要加载各种各样的资源文件,如property文件,xml配置文件,图片文件等等. Java的资源加载策略选择比较多,很多资源加载方法都是基于不同的项目配置,没有一种资. 首先来看看Java中的几种常见的资源加载方法:. 一:通过ResourceBundle类来实现资源加载. 这种方式通常被用来加载多语言支持的property文件,Java语言通过ResourceBundle可以非.

JAVA Web.xml 加载顺序

- - 企业架构 - ITeye博客
web.xml加载过程(步骤):.        1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点:   .    . 2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文..

JAVA 动态(手动)加载jar文件

- - CSDN博客编程语言推荐文章
//filePath 是jar的绝对路径. //里面是一个url的数组,可以同时加载多个. //根据类名加载指定类,例:. //通过反射调用类中的方法,例如调用addFile方法,有1个String参数和一个int参数:. 如果有返回值,则直接返回需要的值,例:. 作者:kingboy123000 发表于2013-10-23 16:12:30 原文链接.