加载载入类文件有什么好处:
增加了灵活性,不是一开始就全部进去,也可以在运行时动态编译,再载入内存 更加灵活
加载生成Class对象fang放在方法区
为什么连接要验证:
因为class文件不一定是通过编译出来的,也可能被二进制读写文件进行了修改,所以需要先检查格式来判断是否正确
会导致初始化的几种情况
初始化只会在首次主动使用该类的时候才会执行一次初始化。
初始化一个子类时也相当于对其父类也进行了主动使用。
访问类的satic final 对象 不会导致初始化,因为final变量在编译时就会存入到调用访问这个常量的方法的类的常量池当中,
调用类并没有直接引用该常量的类,因为不会导致该类的初始化(可以在编译完之后再将Mychild.class删除后运行仍能访问到
Mychild.str3)
A[] a=new A[5];也不会导致初始化
Class.loadClass不会导致初始化,看源码
package VM;
/**
* 初始化子类会等该子类的所有父类都初始化完毕后才会初始化
* 初始化子类只有是属于子类的静态变量才会导致子类初始化,
* Class.forName子类也会导致父类和子类一起初始化
* 且内部类名称前面需要$
* */
public class 验证初始化子类会导致父类初始化 {
static class Myparent1{
static String str="Hello";
static {
System.out.println("Myparent1"+str);
}
}
static class Mychild extends Myparent1{
static final String str3="+666";
static String str2="World";
static {
System.out.println("Mychild"+str2);
}
}
public static void main(String[] args) throws ClassNotFoundException {
//Class.forName("VM.验证初始化子类会导致父类初始化$Mychild");
//System.out.println(Mychild.str);
//System.out.println("------------------");
//System.out.println(Mychild.str2);
System.out.println(Mychild.str3);
}
}
接口的初始化无需等待父类初始化
如果一个类继承于接口,该类初始化会引起其父类的初始化,但是不会引起接口的初始化
静态变量初始化顺序是按照静态变量声明顺序执行
public class 测试静态单例初始化顺序 {
public static void main(String[] args) {
Singleton.getInstance().print();
}
}
class Singleton{
public static int counter1;
private static Singleton singleton=new Singleton();
public static int counter2=5;
public Singleton(){
counter1++;
counter2++;
}
public static Singleton getInstance(){
return singleton;
}
public void print(){
System.out.println(counter1);
System.out.println(counter2);
}
}
/**
* 如果执行System.out.println(MyChild5.a);
* 那么即使Myparent5.class删除了也没事因为a是final在编译的时候就加入了Mytest5的常量池
* 而如果执行System.out.println(MyChild5.a)
* 那么删除.class就不行因为会导致Mychild5.class初始化并会导致接口的加载但不会导致接口的初始化*/
class Z{
public static int print(){
System.out.println(85555);
return 66;
}
}
interface Myparent5{
int a=Z.print();
}
class MyChild5 implements Myparent5{
public static int b=5;
}
public class Mytest5 {
public static void main(String[] args) {
//System.out.println(MyChild5.a);
System.out.println(MyChild5.b);
}
}