我们需要有一个前提的认知:在Java中,类都是主动使用的时候才会加载的!

我们定义下面的两个测试类:
public class testInnerStaticClass {
    static class Inner {
        static int i = 1;
        static {
            System.out.println("静态内部类的静态代码块");
        }

        public Inner() {
            System.out.println("静态内部类的构造方法");
        }
    }

    static int j = 2;
    static {
        System.out.println("外部类的静态代码块");
    }

    public testInnerStaticClass() {
        System.out.println("外部类的构造方法");
    }
}

1. 调用外部类的静态成员变量时会发生什么?

System.out.println(testInnerStaticClass.j);
输出:
外部类的静态代码块
2
发现只初始化了外部类。

2. 调用外部类的构造方法时会发生什么?

System.out.println(new testInnerStaticClass());
输出:
外部类的静态代码块
外部类的构造方法
Test.testInnerStaticClass@1540e19d
和正常的类加载一样,线运行静态代码块,再调用构造方法,也没有初始化内部类。

3. 调用内部类的静态变量时会发生什么?

System.out.println(testInnerStaticClass.Inner.i);
输出:
静态内部类的静态代码块
1

4. 调用内部类的构造方法时会发生什么?

System.out.println(new testInnerStaticClass.Inner());
输出:
静态内部类的静态代码块
静态内部类的构造方法
Test.testInnerStaticClass$Inner@1540e19d

总结

内部类的加载时机和普通的类加载完全一致,都是主动使用才加载。

使用静态内部类/匿名类,不要使用非静态内部类/匿名类.非静态内部类/匿名类会隐式的持有外部类的引用,外部类就有可能发生泄漏。
而静态内部类/匿名类不会隐式的持有外部类引用,外部类会以正常的方式回收,如果你想在静态内部类/匿名类中使用外部类的属性或方法时,可以显示的持有一个弱引用

静态内部类:静态内部类适用于外部类当中,但又不依赖外在的类,使用它可以提高程序的运行效果;

成员内部类:适用于外部类当中,但依赖外在的类,可以自由的使用外部类的变量和方法;

对于不是静态的内部类,首先他是不能有static变量和方法的,其次它的加载和普通类加载也没有区别。