2010-04-29 5 views
13

Also, die Frage ist mehr oder weniger wie ich geschrieben habe. Ich verstehe, dass es wahrscheinlich überhaupt nicht klar ist, damit ich ein Beispiel geben werde.Warum muss eine Unterklassenklasse einer Klasse statisch sein, um die Unterklasse im Konstruktor der Klasse zu initialisieren?

Ich habe Klasse Baum und darin gibt es die Klasse Knoten, und die leeren Konstruktor Baum geschrieben:

public class RBTree { 
    private RBNode head; 

    public RBTree(RBNode head,RBTree leftT,RBTree rightT){ 
     this.head=head; 
     this.head.leftT.head.father = head; 
     this.head.rightT.head.father = head; 
    } 

    public RBTree(RBNode head){ 
     this(head,new RBTree(),new RBTree()); 
    } 

    public RBTree(){ 
     this(new RBNode(),null,null); 
    } 

    public class RBNode{ 
     private int value; 
     private boolean isBlack; 
     private RBNode father; 
     private RBTree leftT; 
     private RBTree rightT; 
    } 
} 

Eklipse mir den Fehler gibt: „Nein umschließenden Instanz vom Typ RBTree ist verfügbar, da die einige Zwischenkonstruktoraufrufe "für den neuen RBTree()" im leeren Konstruktor. Wenn ich jedoch den RBNode zu einer statischen Klasse ändere, gibt es kein Problem.

Warum funktioniert es, wenn die Klasse statisch ist?

BTW, fand ich eine einfache Lösung für den cunstructor:

public RBTree(){ 
    this.head = new RBNode(); 
} 

Also, ich habe keine Ahnung, was das Problem im ersten Teil des Codes ist.

Antwort

24

Grundsätzlich hat eine innere Klasse (ohne den statischen Modifikator) einen impliziten Verweis auf eine Instanz ihrer äußeren Klasse, so dass sie erst erstellt werden kann, wenn die äußere Klasse erstellt wurde. Durch das Erstellen eines Aufrufs an this kann es die äußere Klasse noch nicht referenzieren, da die äußere Klasse erst nach dem Aufruf von super viel aufgebaut wird. Der Fall, der für Sie funktioniert, die Zuweisung zum Kopf geschieht nach dem (impliziten) Aufruf von super, sodass die Klasse so konstruiert ist, dass sie einen Verweis darauf erhält.

Alle diese Regeln verhindern, dass Sie sich selbst in den Fuß schießen, indem Sie auf ein nicht initialisiertes Objekt verweisen und Bad Things (TM) passieren lassen.

+2

Diese Einschränkung hindert mich sauberen Code schreiben. Ich muss hässliche Workarounds erfinden. Trotzdem kann ich auch mit dieser Einschränkung auf nicht initialisierte Variablen zugreifen. Beim Schreiben von hässlichem Code ist es noch einfacher. Um uns davon abzuhalten, in den eigenen Fuß zu schießen, muss Java in der JLS verboten werden. Es ist nichts falsch daran, eine innere Instanz zu erstellen. Inner kann seinen Bezug zum Einschließenden haben, weil das Objekt schon da ist. Die Tatsache, dass es nicht initialisiert ist, macht es nicht falsch. Andernfalls könnten Sie denken, dass es gefährlich ist, das Objekt vor der Initialisierung zu initialisieren. – Val

0

Gute Nachrichten! Die Unterklasse einer inneren Klasse muss NICHT statisch sein!

Hier ist eine Technik, die von Henry Wong bei Code Ranch erklärt wurde, die für äußere Klassen funktioniert, die innere Klassen ableiten. Es funktionierte gut für mich und es macht immer Spaß, zu sehen, wie die Sprachdesigner Java verrenken musste, um die Ecke Fälle :)

http://www.coderanch.com/t/588820/java/java/Extend-class-code-top-level#2681401

Hier ist das Beispiel zu handhaben:

class Demo extends Main.Inner{ 
    public Demo(Main outer) { 
     outer.super(); 
    } 

    void method(){ 
     System.out.println(a); 
    } 
} 
Verwandte Themen