目录
问题:
原理:
外部类与非内部静态类
外部类与静态内部类
加载顺序
总结:
1.非静态内部类依赖于外部类的实例,而静态内部类不依赖于外部类的实例。
2.非静态内部类可以访问外部类的实例变量和方法,而静态内部类只能访问外部类的静态成员。
3.非静态内部类不能定义静态成员,而静态内部类可以定义静态成员。
4.非静态内部类在外部类实例化后才能实例化,而静态内部类可以独立实例化。
5.非静态内部类可以访问外部类的私有成员,而静态内部类不能直接访问外部类的私有成员,需要通过实例化外部类来访问。
问题:
刷完面经,以写博客输出的方式加深面经理解,特此记录。
原理:
从内存的角度更能理解的透彻一些
外部类与非内部静态类
- 非内部静态类实例和外部静态类实例是两个独立的对象,它们分别在堆内存中分配空间。
- 但是,非内部静态类实例隐式持有一个指向外部实例的引用(也就是指针或者说是地址),这个引用是编译器自动生成的。
- 非内部静态类有了外部类的this,那当然可以访问外部类的实例变量,
- 当然也可也访问静态变量,这里要特别注意,即使没有外部类的this,也可也通过类名访问。
外部类与静态内部类
- 外部类与静态内部类,二者之间没啥关系,可以相互独立存在。
- 只是,语法上我们把它俩放在了一块。只是逻辑上的内部与外部,这里一定要理解清楚。
- 说白了,外部类与非内部静态类,是真的存在内外的关系,
- 而外部类与静态内部类,只是把一个静态类放在了一个类里面,因为有非内部静态类这样的称呼,所以我们也就把(一个静态类放在了一个类里面)这样的情况叫做 静态内部类。
- 它的生命周期独立于外部类实例。
加载顺序
- 先加载外部类,后加载内部类,因为内部类必须得拿到外部类的引用才行。
- 静态内部类和外部类二者独立,谁被用到,谁就被加载。
总结:
如果你理解了上面从内存角度的问题,那么接下来这些案例,你都可以从这个角度想通了。
1.非静态内部类依赖于外部类的实例,而静态内部类不依赖于外部类的实例。
原因:
只有外部类实例化后,非内部静态类才能拿到内部类的引用,而静态内部类和外部类二者独立,所以不需要进行实例化后才能拿到引用。
class OuterClass {private String outerField = "Outer Field";class NonStaticInnerClass {void display() {System.out.println(outerField); // 可以直接访问外部类的实例变量}}
}public class Main {public static void main(String[] args) {OuterClass outer = new OuterClass();OuterClass.NonStaticInnerClass inner = outer.new NonStaticInnerClass();inner.display(); // 输出:Outer Field}
}class OuterClass {private static String staticOuterField = "Static Outer Field";static class StaticInnerClass {void display() {System.out.println(staticOuterField); // 可以访问外部类的静态成员}}
}public class Main {public static void main(String[] args) {OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();staticInner.display(); // 输出:Static Outer Field}
}
2.非静态内部类可以访问外部类的实例变量和方法,而静态内部类只能访问外部类的静态成员。
原因:内存区域不一样,而且非静态内部类有外部类的引用,静态内部类与外部类独立,静态内部类单独存储在别的区域。
class OuterClass {private String outerField = "Outer Field";class NonStaticInnerClass {void display() {System.out.println(outerField); // 可以访问外部类的私有实例变量}}
}class OuterClass {private String outerField = "Outer Field";private static String staticOuterField = "Static Outer Field";static class StaticInnerClass {void display() {// System.out.println(outerField); // 编译错误:无法访问实例成员System.out.println(staticOuterField); // 可以访问静态成员// 如果需要访问实例成员,必须通过外部类实例OuterClass outer = new OuterClass();System.out.println(outer.outerField);}}
}
3.非静态内部类不能定义静态成员,而静态内部类可以定义静态成员。
原因:静态成员需要在类加载时就存在,并且不依赖于任何实例,但是非静态内部类需要在外部类加载后才可以,所以不行。
如果你问我为什么不解释静态内部为甚可以定义静态成员,你白看了兄弟!。
class OuterClass {class NonStaticInnerClass {// static int staticField = 10; // 编译错误:非静态内部类不能定义静态成员// static void staticMethod() {} // 编译错误}
}class OuterClass {static class StaticInnerClass {static int staticField = 10; // 允许定义静态成员static void staticMethod() {System.out.println("This is a static method.");}}
}public class Main {public static void main(String[] args) {System.out.println(OuterClass.StaticInnerClass.staticField); // 输出:10OuterClass.StaticInnerClass.staticMethod(); // 输出:This is a static method.}
}
4.非静态内部类在外部类实例化后才能实例化,而静态内部类可以独立实例化。
前面都解释过了,略。
class OuterClass {class NonStaticInnerClass {}
}public class Main {public static void main(String[] args) {OuterClass outer = new OuterClass();OuterClass.NonStaticInnerClass inner = outer.new NonStaticInnerClass();}
}class OuterClass {static class StaticInnerClass {}
}public class Main {public static void main(String[] args) {OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();}
}
5.非静态内部类可以访问外部类的私有成员,而静态内部类不能直接访问外部类的私有成员,需要通过实例化外部类来访问。
class OuterClass {private String privateField = "Private Field";class NonStaticInnerClass {void display() {System.out.println(privateField); // 可以访问外部类的私有成员}}
}class OuterClass {private String privateField = "Private Field";static class StaticInnerClass {void display() {// System.out.println(privateField); // 编译错误:无法直接访问私有成员OuterClass outer = new OuterClass();System.out.println(outer.privateField); // 通过实例访问}}
}