Java类加载的时机

类是什么时候初始化的?类初始化的时候会执行static块,这个是我们知道的。那么我们可以用static块来做个实验。

上面代码输出是:

 

hello world
init
this is a test
这说明了什么?在调用TR.hello_world的时候,类并没有初始化!而是在调用其方法test的时候才初始化的。

这是因为在编译的时候,常量(static final 修饰的)会存入调用类的常量池【这里说的是main函数所在的类的常量池】,调用的时候本质上没有引用到定义常量的类,而是直接访问了自己的常量池。所以,这里调用TR.hello_world的时候,TR并没有初始化。

 

类初始化的时机,有且仅有四个:

1、遇到new、getstatic、putstatic、invokestatic这四条字节码指令的时候。(当使用某个类或接口的静态字段,或者对该字段赋值时(即在字节码中,执行getstaticputstatic指令时),用final修饰的静态字段除外,它被初始化为一个编译时的常量表达式。)

2、使用java.lang.reflect进行反射调用的时候。

3、当初始化一个类的时候,发现其父类还没有初始化,那么先去初始化它的父类。

4、当虚拟机启动的时候,需要初始化main函数所在的类。

 

说到这里,还要说下,静态变量和静态初始化块,普通变量、普通初始化块之间的初始化顺序。

对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是
(静态变量、静态初始化块)>
(变量、初始化块)>
 构造器

http://www.cnblogs.com/jackyrong/archive/2008/08/12/1266161.html

 

链接中说明了,静态变量和静态初始化块的声明顺序决定了初始化的顺序。

静态变量和静态初始化块的初始化时间::早于::普通变量和普通初始化块::早于::构造方法。

并不是完全父类初始化完毕之后,子类才开始初始化。实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

上面报错的地方,有点奇怪。

明明在上面都赋值b=2了的。怎么打印语句就不行呢。

这是因为在类初始化的时候,就规定了,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的,只能赋值,不能访问。

http://blog.csdn.net/imzoer/article/details/8038249

 

时间: 2024-12-10 11:29:03

Java类加载的时机的相关文章

Java类加载及创建实例(new)顺序

Java类加载 1.JVM( Java Virtual Machine,"Java虚拟机" )的类装载器ClassLoader(java类),包括系统类.扩展类.用户编写三种类加载器,负责将java的字节码文件从硬盘读取到JVM中(内存),即首次加载java类时,类的静态成员开辟空间,将常量池存放在方法区内存中,对常量池地址解析,并对java类的静态成员变量.静态块.静态方法进行一次初始化.静态资源在类加载到内存时,只加载一次,而new的对象和对象块,每次都会加载. 2.在使用new关

Java类加载原理解析

1       基本信息 摘要: 每个java开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java的类加载机制是java技术体系中比较核心的部分,虽然和大部分开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查程序中出现的类加载失败等技术问题,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助. 由于关于java类加载的内容较多,所以打算分三篇文章简述一下: 第一篇:java类

java类加载器-关于java类加载的双亲委托机制的一点疑问

问题描述 关于java类加载的双亲委托机制的一点疑问 class Clazz2{ public static void main(String[] args) { ClassLoader classLoader = new ClassLoader() { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { try { FileInputStream fileInputStream =

一篇文章读懂Java类加载器

Java类加载器算是一个老生常谈的问题,大多Java工程师也都对其中的知识点倒背如流,最近在看源码的时候发现有一些细节的地方理解还是比较模糊,正好写一篇文章梳理一下. 关于Java类加载器的知识,网上一搜一大片,我自己也看过很多文档,博客.资料虽然很多,但还是希望通过本文尽量写出一些自己的理解,自己的东西.如果只是重复别人写的内容那就失去写作的意义了. 类加载器结构 类加载器结构 名称解释: 根类加载器,也叫引导类加载器.启动类加载器.由于它不属于Java类库,这里就不说它对应的类名了,很多人喜

classloader-请教大神Java类加载与对象访问的问题

问题描述 请教大神Java类加载与对象访问的问题 当前线程的classloader为classloaderA的一个对象,然后加载了class B,然后我修改了Class B,给B添加了一个新的方法get,我要怎么样才能在不重启JVM的情况下访问到get方法呢?我之前试过把当前线程的classloader换成新的classloaderA对象,但是无法访问到B对象的新方法. 解决方案 JAVA类加载,对象Java类加载与对象调用java之类对象的加载 解决方案二: 类加载器只有在类加载时会起到指示安

Java类加载基本过程详细介绍_java

Java类加载基本过程详细介绍 基本过程: 根据类的全限定名称加载定义类的二进制字节流. 将字节流代表的静态存储结构转化为方法区的运行时数据结构 内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各种数据访问入口  数组类本身不通过类加载器创建,由java虚拟机直接创建,数组类的元素类型由类加载器加载. 数组类的元素类型:数组去掉所有维度后的类型,  文件格式验证: 0xCAFEBABY 魔数开头: 主次版本号当前虚拟机可处理: 常量类型: 索引执行类型: utf8

Java类加载原理及类加载器

Java和其他语言不同的是,Java是运行于Java虚拟机(JVM).这就意味着编译后的代码是以一种和平台无关的格式保存的,而不是某种特定的机器上运行的格式.这种格式和传统的可执行代码格式有很多重要的区别.具体来说,不同于C或者C++程序,Java程序不是一个独立的可执行文件,而是由很多分开的类文件组成,每个类文件对应一个Java类. 另外,这些类文件并不是马上加载到内存,而是当程序需要的时候才加载. 类加载器就是Java虚拟机中用来把类加载到内存的工具.而且,Java类加载器也是用Java实现

java类加载机制

java类加载机制,java对象实例化机制,分享牛博客.分享牛,分享牛原创. 更多参考http://blog.csdn.net/qq_30739519/article/details/51415757一文. 下面声明类看看测试结果: package com.shareniu; public class HelloA { { System.out.println("before class HelloA"); } public HelloA() { System.out.println(

Java程序员的日常 —— Java类加载中的顺序

之前说过Java中类的加载顺序,这次看完继承部分,就结合继承再来说说类的加载顺序. 继承的加载顺序 由于static块会在首次加载类的时候执行,因此下面的例子就是用static块来测试类的加载顺序. package xing.test.thinking.chap7; class A{ static{ System.out.println("A static"); } } class B extends A{ static{ System.out.println("B stat