您的位置:首页 > 编程语言 > Java开发

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.被动使用,不会会导致类的初始化

通过子类引用父类的静态字段,不会导致子类初始化

通过数组定义类引用类,不会触发此类的初始化

调用一个类的常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化

//根据参考例子自己写的
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 虚拟机 对象