java深入学习四之类的加载,连接和初始化
2017-09-10 00:18
316 查看
一、类的加载,连接和初始化
1.查找并加载类的二进制数据,即加载class文件到内存中,将其放在内存的 运行时数据区的方法区,在堆区创建一个java.lang.Class对象,用于封装类在方法区的数据结构。就是说,所创建类的所有属性,方法都能通过Class反射访问到,Class这个对象是虚拟机创建的,是唯一的一个对象。加载的最终产品是这个由虚拟机产生的Class对象。
2.连接:
先验证,确保class文件的正确性;
再准备,为类的静态变量分配内存,将其初始化默认值(静态变量不属于任何一个对象,它属于类);
接着解析,将类的符号引用转化为直接引用。例如,在一个类(类A)的方法中,调用另一个类(类B)的方法(方法C),在解析以前,类B的方法C在A类中只是一个符号引用,由方法C的全名和相关描述符组成。解析会将这个符号引用替换为类B的方法C在方法区的内存位置(这个直接引用就是真正的指针,指向在内存的地址)。虽然java没有使用指针,但是java虚拟机与底层打交道,必须要用指针。
仔细思考解析,class文件中不会直接与内存打交道,不能直接使用内存中的地址,而java虚拟机加载class文件后,会用指针替换掉,据我猜测,这应该也是java能够在不同操作系统运行的原因之一。
3.初始化:为类的静态变量赋予指定的初始值,会进行显式初始化,指赋予初始值或在静态代码块中赋值。
二、java程序对类的使用 参考例子
1.主动使用,会导致类的初始化
new一个对象,创建类的实例
访问类的静态变量(除了final 变量后面跟基本数据类型和String)
调用类的静态方法
通过反射
初始化子类 (当初始化一个类的时候,如果发现其父类还没进行过初始化,则需要先触发其父类的初始化)
标明为启动类 (带有mian方法的类)
2.被动使用,不会会导致类的初始化
通过子类引用父类的静态字段,不会导致子类初始化
通过数组定义类引用类,不会触发此类的初始化
调用一个类的常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化
1.查找并加载类的二进制数据,即加载class文件到内存中,将其放在内存的 运行时数据区的方法区,在堆区创建一个java.lang.Class对象,用于封装类在方法区的数据结构。就是说,所创建类的所有属性,方法都能通过Class反射访问到,Class这个对象是虚拟机创建的,是唯一的一个对象。加载的最终产品是这个由虚拟机产生的Class对象。
2.连接:
先验证,确保class文件的正确性;
再准备,为类的静态变量分配内存,将其初始化默认值(静态变量不属于任何一个对象,它属于类);
接着解析,将类的符号引用转化为直接引用。例如,在一个类(类A)的方法中,调用另一个类(类B)的方法(方法C),在解析以前,类B的方法C在A类中只是一个符号引用,由方法C的全名和相关描述符组成。解析会将这个符号引用替换为类B的方法C在方法区的内存位置(这个直接引用就是真正的指针,指向在内存的地址)。虽然java没有使用指针,但是java虚拟机与底层打交道,必须要用指针。
仔细思考解析,class文件中不会直接与内存打交道,不能直接使用内存中的地址,而java虚拟机加载class文件后,会用指针替换掉,据我猜测,这应该也是java能够在不同操作系统运行的原因之一。
3.初始化:为类的静态变量赋予指定的初始值,会进行显式初始化,指赋予初始值或在静态代码块中赋值。
二、java程序对类的使用 参考例子
1.主动使用,会导致类的初始化
new一个对象,创建类的实例
访问类的静态变量(除了final 变量后面跟基本数据类型和String)
调用类的静态方法
通过反射
初始化子类 (当初始化一个类的时候,如果发现其父类还没进行过初始化,则需要先触发其父类的初始化)
标明为启动类 (带有mian方法的类)
2.被动使用,不会会导致类的初始化
通过子类引用父类的静态字段,不会导致子类初始化
通过数组定义类引用类,不会触发此类的初始化
调用一个类的常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化
//根据参考例子自己写的 package com.thinkInJava.chapter; public class MyObject { /*static{ System.out.println("MyObject初始化"); }*/ public static void main(String[] args) { //会初始化的6种情况 //第1种情况,实例化一个类,就能初始化这个类 //Test test = new Test(); //第2种情况,调用这个类的静态变量(有特殊情况不能初始化) //int num =Test.num; //第3种情况,调用静态方法 //Test.method(); //第4种情况,使用反射能初始化一个类 /*try { Class class1 = Class.forName("com.thinkInJava.chapter.Test"); } catch (Exception e) { e.printStackTrace(); }*/ //第5种情况 调用这个类的子类 //TestChild testChild = new TestChild(); //第6种情况,带有main方法的这个类 //将main方法上面的代码块注释去掉,可以测试 //不会初始化的 //1.子类引用父类静态变量 //int num = TestChild.num; //2.数组引用 //Test [] tests = new Test[3]; //3.带有final staitc 原生数据类型和String //int num = Test.NUM; //String string =Test.STRING; //但是如果不是原生数据类型或String,是final static 类还是会初始化 //TestObject testObject = Test.object; } } class Test{ public static String str ="str"; public static int num = 1; public final static String STRING = "string"; public final static int NUM = 1; public final static TestObject object = new TestObject(); static{ System.out.println("Test初始化"); } public static void method(){ } } class TestObject{ } class TestChild extends Test{ static{ System.out.println("TestChild 初始化"); } }
相关文章推荐
- 深入Java虚拟机JVM类加载初始化学习笔记
- 深入Java虚拟机JVM类加载初始化学习笔记
- 深入Java虚拟机JVM类加载初始化学习笔记
- 深入Java虚拟机JVM类加载初始化学习笔记
- 深入Java虚拟机JVM类加载初始化学习
- Java中类的加载、连接和初始化
- 黑马程序员--Java学习日记之类的加载,反射,动态代理,枚举
- java 类的加载、连接和初始化
- jvm生命周期之类的加载、连接、初始化
- 深入java (类)初探类的加载和初始化顺序
- 深入Java虚拟机之类加载
- java梳理-深入理解类加载及初始化
- java学习——java基础(十)之类加载机制
- java学习之类变量初始化
- 深入理解Java虚拟机之类加载机制
- Java深入研究之类的初始化
- 加载web-inf下的xml文件,java连接oracle的几种情况,telnet,tnsping,sqlplus的一点学习
- java类加载、连接和初始化
- 深入理解JVM八---Java类的连接与初始化
- Java学习总结6——类加载1(类初始化顺序)