Frage

Ich war auf der Suche auf dem Java-Code für LinkedList und bemerkte, dass es die Verwendung einer statischen geschachtelten Klasse gemacht, Entry.

public class LinkedList<E> ... {
...

 private static class Entry<E> { ... }

}

Was ist der Grund für eine statische verschachtelte Klasse, anstatt eine normale innere Klasse?

Der einzige Grund, warum ich denken konnte, war, dass der Eintritt hat keinen Zugriff auf Instanzvariablen, so aus einer OOP-Sicht ist es besser Verkapselung hat.

Aber ich dachte, es könnte andere Gründe geben, vielleicht Leistung. Was könnte es sein?

Hinweis. Ich hoffe, ich habe meine Begriffe richtig aufgestellt, ich hätte es eine statische innere Klasse genannt, aber ich denke, das ist falsch: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

War es hilfreich?

Lösung

Die Sun-Seite verlinkt auf weist einige wichtige Unterschiede zwischen den beiden:

  

Eine verschachtelte Klasse ist ein Mitglied seiner umgebenden Klasse. Nicht-statische verschachtelte Klassen (innere Klassen) haben Zugang zu anderen Mitgliedern der umgebenden Klasse, auch wenn sie privat deklariert ist. Statische verschachtelte Klassen haben keinen Zugang zu anderen Mitgliedern der umgebenden Klasse.
  ...

     

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

Es gibt keine Notwendigkeit für LinkedList.Entry Top-Level-Klasse zu sein, wie es ist nur , die von LinkedList (es gibt einige andere Schnittstellen, die auch statische verschachtelte Klassen namens Entry, wie Map.Entry haben - gleiches Konzept ). Und da es keinen Zugang braucht LinkedList Mitglieder, macht es Sinn für sie statisch zu sein -. Es ist ein viel sauberer Ansatz

Wie Jon Skeet weist darauf hin, , ich denke, es ist eine bessere Idee, wenn Sie eine verschachtelte Klasse verwenden beginnen off mit ihm statisch, sein und dann entscheiden, ob sie auf der Grundlage Ihrer Nutzung wirklich nicht statisch sein muss.

Andere Tipps

Meiner Meinung nach, ist die Frage sollte umgekehrt sein, wenn Sie eine innere Klasse sehen - tut es wirklich muß eine innere Klasse sein, mit der zusätzlichen Komplexität und den impliziten (und nicht expliziter und klarer, IMO) Verweis auf eine Instanz der Klasse enthält?

Wohlgemerkt, ich bin als C # Fan voreingenommen - C # nicht über das Äquivalent von inneren Klassen, obwohl es verschachtelte Typen hat. Ich kann nicht sagen, dass ich innere Klassen verpasst haben noch:)

Es gibt nicht offensichtliche Einprägungsgrad Probleme hier zu berücksichtigen. Da eine nicht-statische innere Klasse einen impliziten Verweis auf seinen ‚äußere‘ Klasse hält, wenn eine Instanz der inneren Klasse stark verwiesen wird, dann wird die äußere Instanz zu stark verwiesen. Dies kann bis zu einem gewissen Kopf-Kratzen führen, wenn die äußere Klasse nicht Müll gesammelt, obwohl es erscheint , dass nichts verweist es.

Nun, für eine Sache, nicht-statische innere Klassen haben ein zusätzliches, verstecktes Feld, das auf die Instanz der äußeren Klasse verweist. Also, wenn der Eintrag Klasse nicht statisch ist, dann neben dem Zugang hat, dass sie nicht brauchen, wäre es um vier Zeiger statt drei tragen.

In der Regel würde ich sagen, wenn Sie eine Klasse definieren, die im Grunde gibt es als eine Sammlung von Datenelementen zu handeln, wie ein „struct“ in C, betrachtet es als statisch zu machen.

statische verschachtelte Klasse ist wie jede andere äußere Klasse, da sie keinen Zugang zu äußeren Klasse Mitglieder hat.

Nur für Convenience-Verpackung wir Club statische verschachtelte Klassen in einer äußeren Klasse zur besseren Lesbarkeit Zweck kann. Abgesehen davon gibt es keine andere Verwendung bei statischer geschachtelten Klasse.

Beispiel für eine solche Art der Nutzung, Sie in Android R.java (Ressourcen) Datei finden. Res Ordner von Android enthalten Layout (mit Bildschirm-Design), ziehbar Ordner (mit Bildern für Projekt verwendet wird), Werte Ordner (die String-Konstanten enthält), etc ..

Sine alle Ordner sind Teil der Res-Ordner, android-Tool erzeugt eine R.java (Ressourcen) Datei, die intern viele statische verschachtelte Klassen enthält für jede ihrer inneren Ordner.

Hier ist das Look and Feel von R.java Datei in android erzeugt: Hier sind sie mit nur für Convenience-Verpackung.

/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.techpalle.b17_testthird;

public final class R {
    public static final class drawable {
        public static final int ic_launcher=0x7f020000;
    }
    public static final class layout {
        public static final int activity_main=0x7f030000;
    }
    public static final class menu {
        public static final int main=0x7f070000;
    }
    public static final class string {
        public static final int action_settings=0x7f050001;
        public static final int app_name=0x7f050000;
        public static final int hello_world=0x7f050002;
    }
}

Statische innere Klasse wird im Builder-Muster verwendet. Statische innere Klasse kann es instanziiert ist äußere Klasse, die nur private Konstruktor hat. So können Sie statische innere Klasse verwenden, um die äußeren Klasse zu instanziiert, die nur private Konstruktor hat. Sie können das gleiche mit der inneren Klasse nicht tun, wie Sie Objekt der äußeren Klasse vor dem Zugriff auf die innere Klasse erstellt haben müssen.

class OuterClass {
    private OuterClass(int x) {
        System.out.println("x: " + x);
    }

    static class InnerClass {
        public static void test() {
            OuterClass outer = new OuterClass(1);
        }
    }
}

public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass.test();
        // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
    }
}

Dies wird der Ausgang x: 1

http://docs.oracle.com/javase/tutorial /java/javaOO/whentouse.html :

  

Verwenden Sie eine nicht-statische verschachtelte Klasse (oder innere Klasse), wenn Sie Zugriff benötigen   zu einer einschließenden Instanz nicht-öffentlichen Bereiche und Methoden. Verwenden Sie einen statischen   verschachtelte Klasse, wenn Sie nicht über diesen Zugriff benötigen.

Einfaches Beispiel:

package test;

public class UpperClass {
public static class StaticInnerClass {}

public class InnerClass {}

public static void main(String[] args) {
    // works
    StaticInnerClass stat = new StaticInnerClass();
    // doesn't compile
    InnerClass inner = new InnerClass();
}
}

Falls nicht statische die Klasse kann nur in einer Instanz der Oberschicht instanziiert werden (also nicht in dem Beispiel, in dem Haupt eine statische Funktion ist)

Einer der Gründe für die statische vs. normale haben mit Classloading zu tun. Sie können nicht eine innere Klasse im Konstruktor instanziiert es Eltern.

PS: Ich habe immer verstanden ‚verschachtelt‘ und ‚innere‘ austauschbar zu sein. Es können feine Nuancen in den Bedingungen, aber die meisten Java-Entwickler würde verstehen, auch nicht.

Nicht statische innere Klassen können in Speicherlecks führen, während statische innere Klasse gegen sich schützen. Wenn die äußere Klasse erhebliche Daten hält, kann er die Leistung der Anwendung senken.

Ich weiß nicht, über die Leistung Unterschied, aber wie Sie sagen, statische verschachtelte Klasse ist kein Teil einer Instanz der umgebenden Klasse. Scheint nur einfacher eine statische verschachtelte Klasse zu erstellen, wenn Sie es wirklich brauchen eine innere Klasse zu sein.

Es ist ein bisschen wie, warum ich immer meine Variablen final in Java machen - wenn sie nicht endgültig sind, ich weiß, dass es etwas komisch mit ihnen los ist. Wenn Sie eine innere Klasse anstelle einer statischen geschachtelten Klasse verwenden, es sollte ein guter Grund sein.

eine statische geschachtelte Klasse verwenden, anstatt nicht-statische kann man Räume in einigen Fällen speichern. Zum Beispiel: Comparator innerhalb einer Klasse Umsetzung, sagen Studenten

.
public class Student {
  public static final Comparator<Student> BY_NAME = new ByName();
  private final String name;
  ...
  private static class ByName implements Comparator<Student> {
    public int compare() {...}
  }
}

Dann sorgt die static, dass der Student-Klasse nur einen Vergleicher hat, anstatt eine neue ist jedes Mal ein neuer Schüler instanziieren Instanz erstellt.

Adavantage der inneren Klasse -

  1. einmaliger Gebrauch
  2. unterstützt und verbessert die Kapselung
  3. Lesbarkeit
  4. Privat-Feld Zugriff

Ohne die äußeren Klasse inneren Klasse bestehende nicht vorhanden ist.

class car{
    class wheel{

    }
}

Es gibt vier Arten von innerer Klasse.

  1. normale Innenklasse
  2. Method Lokale Inner Klasse
  3. Anonyme innere Klasse
  4. statische innere Klasse

Punkt ---

  1. von statischen inneren Klasse, können wir nur Zugriff auf statische Member der äußeren Klasse.
  2. Innen innere Klasse cananot wir statisches Element deklarieren.
  3. Inorder normalen Innenklasse im statischen Bereich der äußeren Klasse aufzurufen.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  4. Inorder normalen Innenklasse in Beispiel Bereich der äußeren Klasse aufzurufen.

    Inner i=new Inner();

  5. Inorder normalen Innenklasse in außerhalb der äußeren Klasse aufzurufen.

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  6. innen Inner-Klasse Diese Zeiger auf innere Klasse.

    this.member-current inner class outerclassname.this--outer class

  7. für innere Klasse anwendbar Modifikator - public, default,

    final,abstract,strictfp,+private,protected,static

  8. Außen $ Innen ist der Name des inneren Klassennamen.

  9. innere Klasse innerhalb Instanzmethode, dann können wir statischen und Instanz Bereich der äußeren Klasse Acess.

10.inner Klasse innerhalb statische Methode, dann können wir nur statisches Feld von

zugreifen

äußeren Klasse.

class outer{

    int x=10;
    static int y-20;

    public void m1() {
        int i=30;
        final j=40;

        class inner{

            public void m2() {
                // have accees x,y and j
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top