java的类加载

165 阅读3分钟

java类的加载过程:

验证-->准备-->解析-->初始化-->使用-->卸载

触发类加载的情况:

1)使用new 、关键字、获取静态属性、设置静态属性、调用静态方法

int value= SuperClass.value 导致父类初始化,子类不初始化

SuperClass.Value = 3 ; 会导致父类初始化,不会导致子类初始化。

SubClass.staticMethod(); 先初始化父类 在初始化子类

SubClass sc = new SubClass(); 先初始化父类 再初始化子类

2):使用反射的时候,若发现类还没有初始化,就会进行初始化

Class clazz = Class.forName("com.hnnd.classloader.SubClass");

3):在初始化一个类的时,若发现其父类没有初始化,就会先初始化父类

SubClass.staticMethod(); 先初始化父类 在初始化子类

启动虚拟机的时候,需要加载包含main方法的类

初始化:类的初始化时类加载的最后一步:执行类的构造器,为所有的类变量进行赋值

结论: 结论一 静态常量初始化过程是,在jvm连接之后,静态常量的初始化,是由调用这个静态常量方法所在的类的常量池中被保存,此时,被调用的静态常量所在的类的class文件就可以被删除,即使被删除,该常量依然有效。调用某个类的静态常量不能初始化该类。

结论二: 按照之前的理解是静态常量被调用不会初始化该静态常量所在的类 但是此处当静态常量的值是一个引用类型的时候,这个时候该静态常量所在的类就会被初始化 故此会先打印我被初始化了,然后在打印a的随机值

结论三:静态变量初始化与静态常量初始化不同,静态变量初始化是在初始化阶段被赋予真实的值比如int a = 2,那么2会被真正的赋值给a。 如果某个类调用了该类的静态变量,那么静态变量所在的类就会被视为被主动调用了。那么该类就会被初始化。 该类如果有静态代码块儿那么静态代码块儿的优先级高于静态变量。 如果该静态变量所在的类中有父类,那么会优先初始化父类。

结论4: 接口的初始化,子接口的初始化不会导致父接口的初始化

结论5: 当静态常量的值是一个引用类型的时候,这个时候该静态常量所在的类就会被初始化

结论6 接口中的变量赋予引用初始值会初始化子接口

对静态的理解 这里的静态,指以static关键字修饰的,包括类,方法,块,字段。

非静态,指没有用static 修饰的。

静态有一些特点:

1.全局唯一,任何一次的修改都是全局性的影响

2.只加载一次,优先于非静态

3.使用方式上不依赖于实例对象。

4.生命周期属于类级别,从JVM 加载开始到JVM卸载结束。

静态内部类和非静态内部类之间到底有什么不同呢?下面是两者间主要的不同。

内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。

(2)非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。

(3)一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。