内部クラスのインターフェイスvsクラス
-
12-09-2019 - |
質問
の違いは何ですからinnerclass宣言を行?またコメント利点?
場合には:クラス内のクラスです。
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();
}
以来、インターフェースはインスタンスが生成され、すべての要素内でのインタフェースアクセスによるドット表記のないレベルスインスタンスを生成けることができないため、インスタンスを生成インターフェースを作って定義されたクラス内のインタフェース透過性を静的ます。
そうする項目クラスの場合はBがしない静的は意味がありません。以来、両ケースAとBはインスタンスを生成方んな意味あるいは静的または内側は入れ子構造があります。停止を与えてくれた応答意味論。また、コンパイラ、ランタイムと行動の相違点の場合やnoneを指定した場合をいいます。な応答意味ください!!!!!専門JVMいます。純VM仕様innardsくださいこの問ではなく文書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(...);
}
応答のクラスを埋め込むことによって、我々はそれが無い他の用途での労働者のAPIの基本的な部分であることを示している。
のMap.Entryクラスは、このイディオムの周知の例である。
まぁ, 利点 きっと少ない授業clutteringプロジェクトのフォルダだけでなく、明;の 欠点 この場内のクラス成長の要件の変更に伴い、 maintenacne なお悪夢です。
私は最初のものは、クラスレベルとアイテムと呼ばれる静的な内部クラスを宣言するだろうと思いました。アイテムはLevels.Itemsで参照することができ、静的になります。
第二は、以下のように、使用Levels.Itemsによってアクセスすることができる単純な内部クラスを宣言しているが
Levels.Items hello = new Levels.Items();
編集:これは完全に間違っている、コメントや他の回答を読んで
。