内部类和静态内部类设计意图
参考原文地址:
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
首先看写法:
class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
//使用上:
StaticNestedClass staticNestenClass = new OuterClass.StaticNestedClass();
OuterClass outerClass = new OuterClass();
InnerClass innerClass = outerClass.new InnerClass();
嵌套类分两种:
一种是静态的,英文更精确称为static nested classes(静态嵌套类).
一种是非静态的, 英文称为inner classes(内部类).
嵌套就是完全和外部类没关系,只是写在你里面。从使用上可以就看出来。在构造静态嵌套类的时候外部类根本没有new出来!只有静态嵌套类存在!
内部类就不同。内部类就是外部类的一部分。有外部类才有内部类。内部类了解外面的全部。从使用上来说,内部类是以外部类对象存在为前提的!
下面是官网解释:
A nested class is a member of its enclosing class. (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
As a member of the OuterClass, a nested class can be declared private, public, protected, or package private. (Recall that outer classes can only be declared public or package private.)
内部类修饰限定符作用按修饰限定符规则来。和嵌套不嵌套无关
为什么使用嵌套类?
1.内部类就是为了外部类使用的,并且仅仅用于外部类的时候。这么做是为了代码的包结构更好。
2.为了增加封装性。有外部类A和内部类B两个类。B要用A的私有变量,而且B自己也不被外部世界所见。
3.增加代码可读性。用到内部类的地方就是外部类!紧密两个类的关系。好找代码。
内部类不允许序列化!
内部类绝对不允许序列化!java编译器在编译内部类的时候会生成一个虚拟的构造函数给内部类。编译后这里面的所有内容在源码里面不一定一一对应。这么做是为了让java编译器编译后的代码拥有源码语法不具有的新特性。但是这种虚拟的构造函数在不同java编译器上有差异。所以你序列化的时候是一个jre环境。反序列化的时候jre又是另一套环境。这可能导致兼容性问题。
内部类的特殊使用:匿名内部类和局部内部类
局部内部类:
局部内部类可以定义在任何{}内,比如for if 方法体
注意:
局部内部类只能获取外部{}中的final变量
从java8开始局部内部类可以访问定义它的方法的参数。
内部类统一规则:内部不能有静态变量和静态方法!!!!
原因: 非static的内部类,在外部类加载的时候,并不会加载它,所以它里面不能有静态变量或者静态方法。static类型的属性和方法,在类加载的时候就需要存在于内存中,你在内部类里写的static JVM找不到!
方法块中不能定义接口(因为接口隐含static修饰)
内部类不能有static变量。除非有final修饰(常量的加载不需要加载类)
匿名内部类是表达式!规则局部内部类
匿名内部类里可以的:
1.声明成员变量
2.额外的方法。即使父类或者接口里没有
3.初始化实例
4.声明一个局部内部类
AClass aClass = new AClass() {
private int a = 1;
class Fool {
int getB() {
return a+1;
}
}
public int getB() {
return a;
}
@Override
public int geta() {
// TODO Auto-generated method stub
return new Fool().getB();
}
};
这么写是正确的。