public class Main {
static {
System.out.println("加载外部类");
}
public Main() {
System.out.println("外部类构造方法");
}
public void newInnerClassInstance() {
InnerClass innerClass = new InnerClass();
}
public void loadStaticInnerClass(){
StaticInnerClass.i=100;
}
public static void main(String[] args) throws Throwable {
Main main = new Main();
main.newInnerClassInstance();
main.loadStaticInnerClass();
}
private class InnerClass {
{
System.out.println("加载内部类");
}
}
static class StaticInnerClass {
static int i=0;
static {
System.out.println("加载静态内部类");
}
}
}
//print:
/**
* 加载外部类
* 外部类构造方法
* 加载内部类
* 加载静态内部类
*/
解释打印的原因:
加载外部类: 当虚拟机启动时,我们指定的main方法的main类,由虚拟机来加载,因此肯定会初始化这个类。
外部类构造方法:由语句Main main=new Main();
引起
加载内部类:由语句main.newInnerClassInstance()#InnerClass innerClass = new InnerClass();
引起,由于内部类没有static块和纯static变量(常量的调用无法引起类加载),所以只能通过new或者反射来引起初始化,这里用new语句创建对象来初始化内部类,并用普通实例代码块来表示初始化了类(无法使用static块)。
加载静态内部类:和普通类加载就没区别,本来静态内部类就和外部类没有太大关联,和普通的类十分接近。由于加载内部类已经用了new语句来初始化类了,这里就采用调用了静态字段的方法来使类初始化。
此外,为什么非静态内部类不能有static字段、static方法、static块?
- 首先,内部类对象必须天然地持有唯一的对外部类对象的引用,一个外部类对象可以有许多内部类对象的引用,但是一个内部类有且必须有唯一一个对外部类对象的引用。
- 暂时没有找到比较靠谱的解释,或许从虚拟机的角度来看会比较容易理解,待定...