图文详解Java中class的初始化顺序
class的装载
在讲class的初始化之前,我们来讲解下class的装载顺序。
以下摘自《Thinking in Java 4》
由于Java 中的一切东西都是对象,所以许多活动
变得更加简单,这个问题便是其中的一例。正如下一章会讲到的那样,每个对象的代码都存在于独立的文件中。除非真的需要代码,否则那个文件是不会载入的。通常,我们可认为除非那个类的一个对象构造完毕,否则代码不会真的载入。由于static 方法存在一些细微的歧义,所以也能认为“类代码在首次使用的时候载入”。
首次使用的地方也是static 初始化发生的地方。装载的时候,所有static 对象和static 代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。当然,static 数据只会初始化一次。
简要的说就是,在类有继承关系时,类加载器上溯造型,进行相关类的加载工作。
比如:
Class B extends Class A 当我们new B()时,类加载器自动加载A的代码
class的初始化顺序
通常是以下这样的初始化顺序:
(static对象和static代码块,依据他们的顺序进行初始化)>成员变量>构造函数
测试代码
public class ClassInit { /** * @Title: main * @Description: 类初始化顺序测试 * @param: @param args * @return: void * @throws */ public static void main(String[] args) { // TODO Auto-generated method stub new B(); } } class A { static{ System.out.println("A的static代码块..."); } public String s1 = prtString("A的成员变量..."); public static String s2 = prtString("A的static变量..."); public A(){ System.out.println("A的构造函数..."); } public static String prtString(String str) { System.out.println(str); return null; } } class B extends A{ public String ss1 = prtString("B的成员变量..."); public static String ss2 = prtString("B的static变量..."); public B(){ System.out.println("B的构造函数..."); } private static A a = new A(); static{ System.out.println("B的static代码块..."); } { System.out.println("代码块..."); } }
测试结果
A的static代码块...
A的static变量...
B的static变量...
A的成员变量...
A的构造函数...
B的static代码块...
A的成员变量...
A的构造函数...
B的成员变量...
代码块...
B的构造函数...
总结
以上就是Java中class的初始化顺序的全部内容,希望对大家使用Java能有所帮助。
相关推荐
-
通过java字节码分析学习对象初始化顺序
复制代码 代码如下: mockery.checking(new Expectations() { { one(new Object()).toString(); will(returnValue("")); } }); 下面写一个写一个简单的类演示这个例子 复制代码 代码如下: public class Test { int i = 1; { int j = 1;
-
java类中元素初始化顺序详解
复制代码 代码如下: public class Test4 { @Test public void test(){ child child = new child(); }} class parent{ public static String parentStaticField = "父类静态变量"; public String parentNormalField ="父类普通变量"; static {
-
Java对象初始化顺序的使用
单一类:(静态成员变量&静态初始化块)<(成员变量&初始化块)<构造函数 复制代码 代码如下: public class 对象初始化顺序 { public static void main(String[] args){ Person p = new Person(); }}class Person{ public static String staticfield ="静态成员变量"; public String fi
-
Java中static静态变量的初始化完全解析
静态变量初始化顺序 1.简单规则 首先先看一段最普遍的JAVA代码: public class Test { public static Test1 t = new Test1(); public static int a = 0; public static int b; public static void main(String[] arg) { System.out.println(Test.a); System.out.println(Test.b); } } class Test1
-
Java数组声明、创建、初始化基础
一维数组的声明方式: type var[]; 或type[] var; 声明数组时不能指定其长度(数组中元素的个数), Java中使用关键字new创建数组对象,格式为: 数组名 = new 数组元素的类型 [数组元素的个数] 实例: TestNew.java: 程序代码: public class TestNew { public static void main(String args[]) { int[] s ; int i ; s = new int[5] ; for(i = 0 ; i
-
java对象初始化顺序验证示例
复制代码 代码如下: public class Derive extends Base { private Member m1 = new Member("Member 1"); { System.out.println("Initial Block()"); } public Derive() { System.out.println("Derive()"); } private Member
-
java父类和子类初始化顺序的深入理解
继承类的构建过程是向外扩散的,子类初始化了,父类一定也初始化了 复制代码 代码如下: class Art{ Art(){ System.out.println("Art"); }}class Drawing extends Art{ Drawing(){ System.out.println("Drawing"); }}public class Cartoon extends Drawing { Cartoon(){ System.out.println(&q
-
浅谈Java变量的初始化顺序详解
规则1(无继承情况下):对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器证明代码: 复制代码 代码如下: public class InitialOrderTest { // 静态变量 public static String staticField = "静态变量"; // 变量 public String field = "变量"; // 静
-
Java类初始化和实例化中的2个“雷区”
在考虑类初始化时,我们都知道进行子类初始化时,如果父类没有初始化要先初始化子类.然而事情并没有一句话这么简单. 首先看看Java中初始化触发的条件: (1)在使用new实例化对象,访问静态数据和方法时,也就是遇到指令:new,getstatic/putstatic和invokestatic时: (2)使用反射对类进行调用时: (3)当初始化一个类时,父类如果没有进行初始化,先触发父类的初始化: (4)执行入口main方法所在的类: (5)JDK1.7动态语言支持中方法句柄所在的类,如果没有初始化
-
图文详解Java中class的初始化顺序
class的装载 在讲class的初始化之前,我们来讲解下class的装载顺序. 以下摘自<Thinking in Java 4> 由于Java 中的一切东西都是对象,所以许多活动 变得更加简单,这个问题便是其中的一例.正如下一章会讲到的那样,每个对象的代码都存在于独立的文件中.除非真的需要代码,否则那个文件是不会载入的.通常,我们可认为除非那个类的一个对象构造完毕,否则代码不会真的载入.由于static 方法存在一些细微的歧义,所以也能认为"类代码在首次使用的时候载入".
-
图文详解Java中的序列化机制
目录 概述 对象序列化和反序列化机制 修改默认的序列化机制 使用transient关键字 自定义readObject.writeObject方法 实现Externalizable接口 serialVersionUID的作用 使用序列化clone 概述 java中的序列化可能大家像我一样都停留在实现Serializable接口上,对于它里面的一些核心机制没有深入了解过.直到最近在项目中踩了一个坑,就是序列化对象添加一个字段以后,使用方系统报了反序列化失败,原因是我们双方的序列化对象没有加上seri
-
详解java中继承关系类加载顺序问题
详解java中继承关系类加载顺序问题 实例代码: /** * Created by fei on 2017/5/31. */ public class SonClass extends ParentClass{ public SonClass(){ System.out.println("SonClass's constructor"); } { System.out.println("SonClass's block");} static { System.out
-
详解Java中的实例初始化块(IIB)
在 Java 语言中的类初始化块 文章中我们简单的介绍了下 Java 中的实例初始化块 ( IIB ).不过我觉得介绍的有点简单了,于是,再写一篇文章详细介绍下吧. Java 语言中,存在三种操作:方法 .构造函数 和 初始化块. 其中初始化块又分为 实例初始化块 ( IIB ) 和 静态初始化块.本章节,我们主要介绍实例初始化块. 实例初始化块 用于初始化实例变量. 实例初始化块 会在初始化类的一个实例时执行,而且在构造函数之前就执行.并且每次创建类的对象时它们都会执行. 实例化块的语法 实例
-
图文详解Java中的字节输入与输出流
目录 字节输入流 字节输入流结构图 FileInputStream类 构造方法: 常用读取方法: 字节输出流 字节输出流结构图: FileOutputStream类 构造方法: 常用写入方法: 总结 字节输入流 java.io.InputStream抽象类是所有字节输入流的超类,将数据从文件中读取出来. 字节输入流结构图 在Java中针对文件的读写操作有一些流,其中介绍最常见的字节输入流. FileInputStream类 FileInputStream流被称为字节输入流,对文件以字节的形式读取
-
图文详解Java的反射机制
目录 1.什么是反射 2.Hello,java反射 3.java程序运行的三个阶段 4.反射相关类 5.反射的优化 6.Class类分析 7.获取Class对象的六种方式 8.类加载机制 动态加载和静态加载 类加载流程概述 加载阶段 连接阶段 初始化 9.通过反射获取类的结构信息 1.什么是反射 反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息. 加载类后,在堆中就产生了一个class类型的对象,这个对象包含了类的完整结构的信息,通过这个对象得到类的结构.这
-
详解JAVA中implement和extends的区别
详解JAVA中implement和extends的区别 extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,Java中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了比如class A extends B implements C,D,E implements是一个类实现一个接口用的关键字,他是用来实现接口中定义的抽象方法. 还有几点需要注意: (1
-
详解java中的四种代码块
在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. 3.静态代码块: 用static{}包裹起来的代码片段,只会执行一次.静态代码块优先于构造块执行. 4.同步代码块: 使用synchronized(){}包裹起来的代码块,在多线程环境下,对共享数据的读写操作是需要互斥进行的,否则会导致数据的不一致性.同步代码块需要写在方法中. 二.静态代码块和构造
-
详解Java 中的UnitTest 和 PowerMock
学习一门计算机语言,我觉得除了学习它的语法外,最重要的就是要学习怎么在这个语言环境下进行单元测试,因为单元测试能帮你提早发现错误:同时给你的程序加一道防护网,防止你的修改破坏了原有的功能:单元测试还能指引你写出更好的代码,毕竟不能被测试的代码一定不是好代码:除此之外,它还能增加你的自信,能勇敢的说出「我的程序没有bug」. 每个语言都有其常用的单元测试框架,本文主要介绍在 Java 中,我们如何使用 PowerMock,来解决我们在写单元测试时遇到的问题,从 Mock 这个词可以看出,这类问题主
-
详解JAVA中接口的定义和接口的实现
1.接口的定义 使用interface来定义一个接口.接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成.定义接口的基本格式如下: [修饰符] interface 接口名 [extends 父接口名列表]{ public static final 常量; public abstract 方法; } 修饰符:可选,用于指定接口的访问权限,可选值为public.如果省略则使用默认的访问权限. 接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标
随机推荐
- 基于java TCP网络通信的实例详解
- zf框架db类的分页示例分享
- set_include_path在win和linux下的区别
- C语言怎么获得进程的PE文件信息
- 用C实现PHP扩展 Image_Tool 图片常用处理工具类的使用
- python处理按钮消息的实例详解
- 20行Android代码写一个CircleImageView
- myeclipse10配置tomcat教程详解
- Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一)
- Android横竖屏幕切换生命周期详解
- asp.net 获取某个时间段的星期并以表格形式排列出来
- JS实现php的伪分页
- 如何进行客户VLAN组建配置划分
- 解决Charles抓包https时,无法查看CONNECT请求的问题
- java并发之AtomicInteger源码分析
- Node4-5静态资源服务器实战以及优化压缩文件实例内容
- nginx中的listen指令实例解析
- 使用Python来开发微信功能
- ASP.NET 4.0配置文件中的ClientIDMode属性详解
- vue实现2048小游戏功能思路详解