Frage

Was ist der Unterschied zwischen diesen beiden Erklärungen Innerclass? Kommentar auch auf Vorteile / Nachteile?

Fall A:. Klasse innerhalb einer Klasse

public class Levels {   
  static public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

und Fall B:. Klasse innerhalb Schnittstelle

public interface Levels{

  public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

Aus Korrektur:. Um die Platzierung von getvalue Methode

Weitere Informationen: Ich bin in der Lage Artikel Klasse in beiden Fällen A und B in einer anderen Klasse zu instanziieren, die nicht-Schnittstelle nicht implementieren AT ALL.

public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
 Levels.Items items = new Levels.Items();
}

Da eine Schnittstelle nicht instanziiert wird, werden alle Elemente innerhalb einer Schnittstelle sind durch Punktnotation ohne Schnittstelle STUFEN instanziiert, nur weil Sie eine Schnittstelle nicht instanziiert können -. Effektiv eine Klasse machen innerhalb einer Schnittstelle definiert durchlässig für statische Referenz

So sagt, dass Artikel Klasse im Fall B nicht statisch ist nicht sinnvoll. Da beiden Fälle A und B die gleiche Art und Weise instanziert werden, ich bin nicht auf der Suche nach Semantik auf, was statisch oder inneren oder verschachtelt. Hör auf, mir Antworten auf Semantik geben. Ich möchte den Compiler, Laufzeit und Verhaltensunterschiede / Vorteile, oder wenn keiner dann sagen. Keine Antworten auf Semantik bitte !!!!! Ein Experte für JVM oder .NET-VM-Spezifikation Innereien bitte diese Antwort Frage und nicht als Text Buch semanticissiests.

War es hilfreich?

Lösung

Statische innere Klassen sind meist ähnlich wie Top-Level-Klassen, mit Ausnahme der inneren Klasse hat Zugriff auf alle statisch Variablen und Methoden der umschließenden Klasse. Der umschließende Klassenname ist mit dem Paket-Namensraum der inneren Klasse effektiv angehängt. eine Klasse als statische innere Klasse, indem er erklärt, kommunizieren Sie, dass die Klasse untrennbar mit dem Kontext der umgebenden Klasse gebunden ist irgendwie.

Nicht-statische innere Klassen sind weniger verbreitet. Der Hauptunterschied besteht darin, dass Instanzen einer nicht statischen inneren Klasse einen impliziten Verweis auf eine Instanz der einschließenden Klasse enthalten, und als Ergebnis haben Zugriff auf Instanzvariablen und Methoden dieser umschließenden Klasseninstanz. Dies führt zu einigen seltsam aussehende Instanziierung Idiome, zum Beispiel:

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(); 

Nicht-statische innere Klassen sind viel inniger gebunden an ihre einschließenden Klassen als statische innere Klassen. Sie haben gültige Nutzungen (zB Iteratoren oft als nicht-statische innere Klassen innerhalb der Klasse der Datenstruktur implementiert werden sie durchlaufen).

Es ist ein häufiger Fehler, eine nicht-statische innere Klasse zu erklären, wenn man nur wirklich das statische innere Klasse Verhalten benötigen.

Andere Tipps

Eine static innere Klasse ist eine verschachtelte Klasse, und die nicht-statisch ist eine innere Klasse genannt. Weitere hier suchen.

Allerdings Ich mag einen Auszug aus dem gleichen Link zu zitieren.

  

Eine statische verschachtelte Klasse interagiert mit   die Instanz Mitglieder seiner äußeren   Klasse (und andere Klassen) wie   andere Top-Level-Klasse. In der Tat,   eine statische verschachtelte Klasse ist behaviorally   eine Top-Level-Klasse, die verschachtelt worden   in einer anderen Top-Level-Klasse für   Verpackung Komfort.

Sie haben nicht das Wort static im zweiten Fall verwenden. Und Sie denken, es würde implizit eine Schnittstelle, weil seine static werden. Sie haben Recht, dass angenommen wird.

Sie können die innere Klasse in Ihrer Schnittstelle instanziiert, wie eine statische verschachtelte Klasse, denn es ist wirklich ein static Klasse verschachtelt.

Levels.Items hello = new Levels.Items();

Also, die obige Aussage wird gültig in Ihren beiden Fällen . Ihr erster Fall ist die statischen verschachtelte Klasse, und im zweiten Fall Sie nicht angegeben static, aber auch dann wäre es eine statische verschachtelte Klasse sein, weil seine in der Schnittstelle. daher kein Unterschied andere dann die Tatsache, dass man in einer Klasse verschachtelt ist, und die andere in einer Schnittstelle .

Normalerweise eine innere Klasse in einer Klasse, nicht in der Schnittstelle , würde wie unter instanziiert werden.

Levels levels = new Levels();
Levels.Items items = levels.new Items();

Darüber hinaus ist eine „nicht-statische“ innere Klasse wird eine implizite Bezugnahme auf seine äußeren Klasse. Dies ist nicht der Fall mit „statischer“ geschachtelte Klasse.

Wenn Sie eine verschachtelte Klasse in einer Schnittstelle deklarieren es ist immer öffentliche und statisch . Also:

public interface Levels{
    class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

Ist genau das gleiche wie

public interface Levels{
    public static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

Und selbst

public interface Levels{
    static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

Ich habe habe dies mit javap -verbose und sie alle produzieren

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;


}

Die Beispiele, die Sie von verschachtelten / inneren Klassen geben sind (IMO) schlechte Beispiele. Neben dem zweiten Beispiel ist nicht gültig Java, da eine Schnittstelle nur (implizit) abstrakte Methoden erklären kann. Hier ist ein besseres Beispiel:

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(...);
}

, um die Response-Klasse Durch die Einbettung wir an, dass es ein grundlegender Bestandteil der Worker API ohne andere Anwendungen ist.

Die Map.Entry Klasse ist ein bekanntes Beispiel für dieses Idiom.

IMHO, Vorteil: ist, dass Sie weniger Klassen unübersichtlich Ihrem Projektordner bekam, wenn sie sind trivial; Nachteil ist, dass, wenn Ihre innere Klasse entlang der Anforderung ändern bekommen wächst, die maintenacne wird Ihr Alptraum.

Ich dachte, dass der erste, der eine Klasse Level und eine statische innere Klasse namens Artikel erklären würde. Artikel von Levels.Items verwiesen werden könnte, und wäre statisch.

Während der zweite wäre eine einfache innere Klasse erklären, die unter Verwendung von Levels.Items zugegriffen werden kann, wie im folgenden Beispiel:

Levels.Items hello = new Levels.Items();

EDIT: Das ist völlig falsch, lesen Sie die Kommentare und andere Antworten

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top