我不认为上述答案中真正的区别变得清晰。
首先要使条款正确:嵌套类是一个类,它包含在源代码级别的另一个类中。
如果使用static修饰符声明它,它是静态的。
非静态嵌套类称为内部类。(我留在非静态嵌套类。)
到目前为止,马丁的回答是正确的。但是,实际的问题是:声明嵌套类静态的目的是什么?
如果您只想将类保持在一起,或者如果嵌套类专门用于封闭类,则可以使用静态嵌套类。静态嵌套类与每个其他类之间没有语义差异。
非静态嵌套类是一种不同的野兽。与匿名内部类相似,这种嵌套类实际上是闭包。这意味着他们捕获周围的范围及其封闭的实例并使其可访问。也许一个例子将澄清这一点。查看Container的这个存根:public class Container {
public class Item{
Object data;
public Container getContainer(){
return Container.this;
}
public Item(Object data) {
super();
this.data = data;
}
}
public static Item create(Object data){
// does not compile since no instance of Container is available
return new Item(data);
}
public Item createSubItem(Object data){
// compiles, since 'this' Container is available
return new Item(data);
}}
在这种情况下,您希望从子项目到父容器的引用。使用非静态嵌套类,这没有一些工作。您可以使用语法访问Container的封闭实例Container.this。
更多核心解释如下:
如果查看编译器为(非静态)嵌套类生成的Java字节码,它可能会变得更加清晰:// class version 49.0 (49)// access flags 33public class Container$Item {
// compiled from: Container.java
// access flags 1
public INNERCLASS Container$Item Container Item
// access flags 0
Object data // access flags 4112
final Container this$0 // access flags 1
public getContainer() : Container
L0
LINENUMBER 7 L0
ALOAD 0: this
GETFIELD Container$Item.this$0 : Container
ARETURN
L1
LOCALVARIABLE this Container$Item L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 1
public (Container,Object) : void
L0
LINENUMBER 12 L0
ALOAD 0: this
ALOAD 1
PUTFIELD Container$Item.this$0 : Container
L1
LINENUMBER 10 L1
ALOAD 0: this
INVOKESPECIAL Object.() : void
L2
LINENUMBER 11 L2
ALOAD 0: this
ALOAD 2: data
PUTFIELD Container$Item.data : Object
RETURN
L3
LOCALVARIABLE this Container$Item L0 L3 0
LOCALVARIABLE data Object L0 L3 2
MAXSTACK = 2
MAXLOCALS = 3}
如您所见,编译器会创建一个隐藏字段Container this$0。这是在构造函数中设置的,该构造函数具有Container类型的附加参数以指定封闭实例。您无法在源中看到此参数,但编译器会为嵌套类隐式生成它。
马丁的例子OuterClass.InnerClass innerObject = outerObject.new InnerClass();
会被编译成类似(在字节码中)的调用new InnerClass(outerObject)
为了完整起见:
匿名类是刚刚没有与之关联的名称,并且不能在以后引用非静态嵌套类的一个很好的例子。