1. public class Main {
    2. static {
    3. System.out.println("加载外部类");
    4. }
    5. public Main() {
    6. System.out.println("外部类构造方法");
    7. }
    8. public void newInnerClassInstance() {
    9. InnerClass innerClass = new InnerClass();
    10. }
    11. public void loadStaticInnerClass(){
    12. StaticInnerClass.i=100;
    13. }
    14. public static void main(String[] args) throws Throwable {
    15. Main main = new Main();
    16. main.newInnerClassInstance();
    17. main.loadStaticInnerClass();
    18. }
    19. private class InnerClass {
    20. {
    21. System.out.println("加载内部类");
    22. }
    23. }
    24. static class StaticInnerClass {
    25. static int i=0;
    26. static {
    27. System.out.println("加载静态内部类");
    28. }
    29. }
    30. }
    31. //print:
    32. /**
    33. * 加载外部类
    34. * 外部类构造方法
    35. * 加载内部类
    36. * 加载静态内部类
    37. */

    解释打印的原因:
    加载外部类: 当虚拟机启动时,我们指定的main方法的main类,由虚拟机来加载,因此肯定会初始化这个类。
    外部类构造方法:由语句Main main=new Main();引起
    加载内部类:由语句main.newInnerClassInstance()#InnerClass innerClass = new InnerClass();引起,由于内部类没有static块和纯static变量(常量的调用无法引起类加载),所以只能通过new或者反射来引起初始化,这里用new语句创建对象来初始化内部类,并用普通实例代码块来表示初始化了类(无法使用static块)。
    加载静态内部类:和普通类加载就没区别,本来静态内部类就和外部类没有太大关联,和普通的类十分接近。由于加载内部类已经用了new语句来初始化类了,这里就采用调用了静态字段的方法来使类初始化。


    此外,为什么非静态内部类不能有static字段、static方法、static块?

    • 首先,内部类对象必须天然地持有唯一的对外部类对象的引用,一个外部类对象可以有许多内部类对象的引用,但是一个内部类有且必须有唯一一个对外部类对象的引用。
    • 暂时没有找到比较靠谱的解释,或许从虚拟机的角度来看会比较容易理解,待定…