嵌套类的四种类型
静态成员类、非静态成员类、匿名类、局部类
第 2 3 4 种叫内部类
一般来说 内部类的最常用的场景是作为外部类的辅助类, 也就是他自身单独是没有什么作用的, 他是辅佐外部类来实现功能的
静态成员类特殊之处
它被 static 修饰, 所以它其实是属于 class 的, 而没有被static 修饰是属于实例的, 非static 成员类在实例化的时候需要先实例化外部类
public class A {
public static void main(String[] args) {
// B 是 static 类, 可以直接 new
B b = new B();
// C 是非static 类, 必须先 new 外部类A , 如果直接写 new C(); 编译报错
C c = new A().new C();
}
public static class B {
}
public class C {
}
}
不仅如此, 内部类一旦实例化, 他就与外部类的实例已经绑定, 这种关系无法修改,无法解绑. 进而也会影响 gc (外部实例和内部实例只要有一个无法被回收, 那就都无法被回收)
A a = new A();
C c = a.new C("c1");
// 此时, c 所指向的外部类就被绑定为 a , 无法修改
正因为非静态成员类需要先实例化外部类, 所以它需要消耗额外的计算与空间. 也因此 , 优先考虑 static 关键字, 以便内部类可以独立实例化.
局部类 : 方法内部的类
同局部变量一样, 局部类不能使用访问权限修饰符( public private protected)
局部类有效性只在方法内部, 方法外无法访问
无法声明static 字段和方法
public void method(){
class D {
private String dName;
}
}
匿名类
匿名类有很多使用限制, 比如他的类是匿名的, 因为无法使用 instanceof 判断式
匿名类无法扩展实现接口
匿名类的扩展成员变量无法被外部访问,只能访问那些父类中的变量和方法 ( 因为匿名类是被他的父类所引用的, 对于程序而言,只能拿到接口或者父类引用, 也就只能访问父类或接口的变量与方法)
public void method() {
// 匿名类一般是在当前场景下 需要唯一特殊扩展一个类
// 常见情况,. 实现LinkedHashMap 最大容量 100, 也就是常见的缓存场景中限制最大缓存数
Map<String, String> m = new LinkedHashMap() {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > 100;
}
};
}
总结上面说的4种类:
局部类: 作用域只在方法内, 不能有权限修饰符
匿名类 : 扩展出的方法和属性只能在匿名类内部使用( 实现LinkedHashMap)
非静态成员类: 实例化时候依赖外部类, 并且会始终持有外部类的引用, 可能影响 gc (HashMap.EntrySet)
静态成员类 : 与外部类实例解绑, 可以当做独立类 (各种 builder)
最后, 注意我们的题目: 优先 , 不是 一定, 静态成员类的适用性更好, 优先考虑静态成员类