-
12-09-2019 - |
题
是什么这两个内部类声明之间的差异?上优点/缺点也评论?
情况A:一个类中的类
public class Levels {
static public class Items {
public String value;
public String path;
public String getValue() {
return value;}
}
}
和情况B:界面内类
public interface Levels{
public class Items {
public String value;
public String path;
public String getValue() {
return value;}
}
}
制成校正:到GetValue方法的放置
进一步信息: 我能够实例在这两种情况下项目A类和B在不实现接口在所有其他类。
public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
Levels.Items items = new Levels.Items();
}
由于接口未初始化,所有的接口内的元素是由点表示法访问,无需简单地实例化,因为你不能实例的接口LEVELS接口 - 有效地使可渗透静态参考的界面内定义的类
所以说,在情况B类项目不是静态的没有意义。由于这两种情况下,A和B被实例化以同样的方式,我不是在寻找什么是静态或内或嵌套语义。别给我答案的语义。我希望编译器,运行时和行为上的差异/优势;如果没有则这样说。没有更多的语义请回答!!!!!在JVM或.NET VM规范内脏的专家取悦这个答案的问题,而不是课本semanticissiests。
解决方案
静态内部类大多是类似于顶级类,除了内部类具有访问所有的静态变量和封闭类的方法。封闭类名被有效地追加到内部类的包名称空间。通过声明类作为静态内部类,你正在通信,所述类被以某种方式不可分离地绑在封闭类的上下文中。
非静态内部类是不太常见的。的主要区别在于,非静态内部类的实例包含对封闭类的一个实例的隐式引用,并且作为结果可以访问实例变量和其外围类实例的方法。这导致一些奇寻找实例成语,例如:
Levels levels = new Levels(); // first need an instance of the enclosing class
// The items object contains an implicit reference to the levels object
Levels.Items items = levels.new Items();
非静态内部类更紧密地依赖于他们的封闭类不是静态内部类。它们具有有效的用途(例如迭代器被作为非静态内部类的类它们遍历的数据结构内经常实现)。
这是一个常见的错误申报非静态内部类时,你只真正需要的静态内部类的行为。
其他提示
这是static
内部类是一个嵌套类,且非静态称为内部类。如需更多信息,看这里。
然而,我喜欢来自同一链接引用的摘录。
一个静态嵌套类与之交互 其外的实例成员 类(其他类)就像 任何其他顶级类。有效, 静态嵌套类是行为上 已被嵌套在顶级类 在另一个顶级类 包装的便利性。
您没有在第二种情况下使用这个词static
。你认为它会在暗中被static
,因为它的接口。你是对在假定。
您可以实例化内部类在你的界面,就像一个静态嵌套类,因为它真的是一个static
嵌套类。
Levels.Items hello = new Levels.Items();
因此,上面的语句将在这两种情况下,你的有效的。你的第一种情况是静态的嵌套类的,而在第二种情况下,你没有指定static
,但即使如此,这将是一个静态嵌套类,因为它的界面。的因此,没有区别其他然后一个事实,就是嵌套在一个类,并且另一个在接口强>
在一类通常的内部类,的未在接口下,将被实例化的像的下方。
Levels levels = new Levels();
Levels.Items items = levels.new Items();
<强>此外,“非静态”内部类将有其外类隐式引用。这不是“静态”嵌套类的情况。强>
如果您在接口中声明嵌套类总是公共和静态的。所以:
public interface Levels{
class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
时完全相同
public interface Levels{
public static class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
和甚至
public interface Levels{
static class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
我已经与javap的-verbose选中此,它们都产生
Compiled from "Levels.java"
public class Levels$Items extends java.lang.Object
SourceFile: "Levels.java"
InnerClass:
public #14= #3 of #23; //Items=class Levels$Items of class Levels
minor version: 0
major version: 50
Constant pool:
const #1 = Method #4.#21; // java/lang/Object."<init>":()V
const #2 = Field #3.#22; // Levels$Items.value:Ljava/lang/String;
const #3 = class #24; // Levels$Items
const #4 = class #25; // java/lang/Object
const #5 = Asciz value;
const #6 = Asciz Ljava/lang/String;;
const #7 = Asciz path;
const #8 = Asciz <init>;
const #9 = Asciz ()V;
const #10 = Asciz Code;
const #11 = Asciz LineNumberTable;
const #12 = Asciz LocalVariableTable;
const #13 = Asciz this;
const #14 = Asciz Items;
const #15 = Asciz InnerClasses;
const #16 = Asciz LLevels$Items;;
const #17 = Asciz getValue;
const #18 = Asciz ()Ljava/lang/String;;
const #19 = Asciz SourceFile;
const #20 = Asciz Levels.java;
const #21 = NameAndType #8:#9;// "<init>":()V
const #22 = NameAndType #5:#6;// value:Ljava/lang/String;
const #23 = class #26; // Levels
const #24 = Asciz Levels$Items;
const #25 = Asciz java/lang/Object;
const #26 = Asciz Levels;
{
public java.lang.String value;
public java.lang.String path;
public Levels$Items();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 2: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLevels$Items;
public java.lang.String getValue();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #2; //Field value:Ljava/lang/String;
4: areturn
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LLevels$Items;
}
你给嵌套/内部类的实例是(IMO)坏的例子。除了第二个例子是不是有效的Java,因为每个接口只能声明(隐含的)抽象方法。这里有一个更好的例子:
public interface Worker {
public class Response {
private final Status status;
private final String message;
public Response(Status status, String message) {
this.status = status; this.message = message;
}
public Status getStatus() { return status; }
public String getMessage() { return message; }
}
...
public Response doSomeOperation(...);
}
通过嵌入Response类,我们表明它是工人API的没有其他用途的基本组成部分。
在Map.Entry的类是这种习惯用法的一个众所周知的例子。
恕我直言,的优势是你有较少的班级混乱,如果他们微不足道的项目文件夹;在劣势是,当你的内部类相处的需求变化越来越大,在 maintenacne 成为你的噩梦。
我认为第一个将声明一个类水平和称为项目的静态内部类。项可以由Levels.Items被引用和将是静态的。
虽然第二将宣布一个简单的内部类,其可以通过使用Levels.Items在以下进行访问,如:
Levels.Items hello = new Levels.Items();
编辑:这是完全错误的,读出的评论和其他答复
。