Ist keine umschließende Klasse Java


366

Ich versuche ein Tetris-Spiel zu erstellen und erhalte den Compilerfehler

Shape is not an enclosing class

wenn ich versuche ein Objekt zu erstellen

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

Ich benutze innere Klassen für jede Form. Hier ist ein Teil meines Codes

public class Shapes {
    class AShape {
    }
    class ZShape {
    }
}

Was mache ich falsch ?


160
new Shape().new ZShape();. Die Klasse ZShapebenötigt eine umschließende Instanz, die instanziiert werden muss.
Sotirios Delimanolis

4
Verschieben Sie die innere Klasse in eine separate Datei
Dimmduh

@ Dimduh Kommentar sollte in diesem Fall die Antwort sein. Sie sollten keine inneren Klassen sein. Wenn Sie sie verschieben, werden die anderen vorhandenen Probleme mit der Shape-Klasse identifiziert.
Jeremiah Adams

Um die Frage hier nicht zu beantworten, kann ich jedoch vorschlagen, die Vererbung hier wo zu verwenden AShapeund ZShapedie Basisklasse zu erweitern Shapes. Das Verschachteln von Klassen ist kein wirklich gutes Design für dieses Problem.
Paramvir Singh Karwal

Antworten:


492

ZShape ist nicht statisch und erfordert daher eine Instanz der äußeren Klasse.

Die einfachste Lösung besteht darin, ZShape und jede verschachtelte Klasse zu erstellen, staticwenn Sie können.

Ich würde auch irgendwelche Felder machen finaloder static finaldas kannst du auch.


13
Das ZShape staticvöllige Besiegen des Zwecks dessen, was er zu tun versucht, ist das Instanziieren einer Kopie von ZShape.
Cardano

17
@ Cardano staticmacht es einfacher, nicht schwerer.
Peter Lawrey

12
Eine andere einfache Lösung besteht darin, die einschließende Klasse die innere Klasse instanziieren zu lassen, dh ZShape folgendermaßen zu erhalten : ZShape myShape = new Shape().instantiateZShape();. Dies impliziert, dass die ZShape, die Sie erhalten, ohne eine Form nicht existiert, was hier beabsichtigt ist.
Vince

@Peter Lawrey Wie haben Sie festgestellt, dass alle Shape-Instanzen dieselbe ZShape verwenden müssen? Ich verstehe es nicht von seiner Quelle.
Der unglaubliche

2
Es gibt 2 Fälle, wenn wir statische oder eine Instanz wollen. Es hilft nicht immer, es statisch zu machen.
Yogesh Chuahan

177

Angenommen, RetailerProfileModel ist Ihre Hauptklasse und RetailerPaymentModel ist eine innere Klasse darin. Sie können ein Objekt der inneren Klasse außerhalb der Klasse wie folgt erstellen:

RetailerProfileModel.RetailerPaymentModel paymentModel
        = new RetailerProfileModel().new RetailerPaymentModel();

34
Diese Antwort war wirklich hilfreich, ich wusste nie, dass man zweimal hintereinander neu anrufen kann (und ich
mache

1
Sie können sicher einen neuen Operator beliebig oft aufrufen, bis Sie keine Referenz dieses Objekts mehr behalten möchten.
Vishal Kumar

1
Wenn ein Objekt der inneren Klasse auf diese Weise erstellt wird, wie greift es auf die Mitglieder der äußeren Klasse zu?
Xingang Huang

1
Innerhalb der inneren Klasse selbst können Sie OuterClass.this verwenden. Ich glaube jedoch nicht, dass es eine Möglichkeit gibt, die Instanz von außerhalb des Codes der inneren Klasse abzurufen. Natürlich können Sie jederzeit Ihre eigene Eigenschaft einführen: public OuterClass getOuter () {return OuterClass.this; }
Vishal Kumar

Funktioniert für Tests:underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
Felvhage

48

Ich würde vorschlagen, die nicht statische Klasse nicht in eine statische Klasse zu konvertieren, da in diesem Fall Ihre innere Klasse nicht auf die nicht statischen Mitglieder der äußeren Klasse zugreifen kann.

Beispiel:

class Outer
{
    class Inner
    {
        //...
    }
}

In einem solchen Fall können Sie also Folgendes tun:

Outer o = new Outer();
Outer.Inner obj = o.new Inner();

Was ist mit Outer.Inner obj = (neues Outer) .new Inner ();
Hussain KMR Behestee

1
@ HussainKMRBehestee, nein das würde sicher nicht funktionieren. Dies würde jedoch funktionierenOuter.Inner obj = new Outer().new Inner();
Amit Upadhyay

Aber Amit, es funktioniert bei mir. Ich würde mich freuen, wenn Sie erklären könnten, warum es nicht funktionieren sollte.
Hussain KMR Behestee

1
@HussainKMRBehestee, Erklärung: Ich kann nur vermuten, dass die Grammatik in Java besagt, dass wir zum Instanziieren einer Klasse den Konstruktor aufrufen müssen und beim Aufrufen des Konstruktors ()obligatorisch sind. C, C ++ ist jedoch kein Muss. Hier ist ein Beispiel, das nicht funktioniert. Außerdem habe ich diesen Beitrag gefunden . Hier erfahren Sie mehr über die Grammatik in Java und wie sie analysiert werden. Ich würde gerne einen Beispielfall sehen, wenn diese Syntax für Sie funktioniert.
Amit Upadhyay

1
Oh, mein Schlechtes, es war ein Tippfehler, Outer.Inner obj = (new Outer ()). New Inner (); Ich hoffe, diesmal ist es in Ordnung und danke, dass du das bemerkt hast.
Hussain KMR Behestee


10

Manchmal müssen wir eine neue Instanz einer inneren Klasse erstellen, die nicht statisch sein kann, da sie von einigen globalen Variablen der übergeordneten Klasse abhängt. Wenn Sie in dieser Situation versuchen, die Instanz einer inneren Klasse zu erstellen, die nicht statisch ist, wird ein not an enclosing classFehler ausgegeben.

Nehmen wir am Beispiel der Frage, was ist, wenn ZShapees nicht statisch sein kann, weil es eine globale Variable von benötigtShape Klassenvariable benötigt wird?

Wie können Sie eine neue Instanz von erstellen? ZShape ? Das ist wie:

Fügen Sie der übergeordneten Klasse einen Getter hinzu:

public ZShape getNewZShape() {
    return new ZShape();
}

Greifen Sie wie folgt darauf zu:

Shape ss = new Shape();
ZShape s = ss.getNewZShape();


1

Ich bin auf das gleiche Problem gestoßen. Ich habe gelöst, indem ich eine Instanz für jede innere öffentliche Klasse erstellt habe. In Bezug auf Ihre Situation schlage ich vor, dass Sie eine andere Vererbung als innere Klassen verwenden.

public class Shape {

    private String shape;

    public ZShape zShpae;
    public SShape sShape;

    public Shape(){
      int[][] coords =  noShapeCoords;
      shape = "NoShape";
      zShape = new ZShape();
      sShape = new SShape();
    }

    class ZShape{
      int[][] coords =  zShapeCoords;
      String shape = "ZShape";
    }

    class SShape{
      int[][] coords = sShapeCoords;
      String shape = "SShape";
    }

 //etc
}

dann kannst du neue Form (); und besuchen Sie ZShape über shape.zShape;


1
Eine falsche Lösung. Logischer Fehler. Wenn für die innere Klasse (z. B. ZShape) ein Feld festgelegt werden muss, müssen Sie es im Konstruktor der äußeren Klasse abrufen! öffentliche Form (String field1_innerClass, int field2_innerClass ...) {zShape = neue ZShape (String field1_innerClass, int field2_innerClass ...) ...}}
Mohsen Abasi

1

Die verschachtelte Klasse muss nicht statisch sein, sondern muss öffentlich sein

public class Test {
    public static void main(String[] args) {
        Shape shape = new Shape();
        Shape s = shape.new Shape.ZShape();
    }
}

1

Eine Sache, die ich beim Lesen der akzeptierten Antwort zunächst nicht erkannte, war, dass es im Grunde dasselbe ist, eine innere Klasse statisch zu machen, als sie in eine eigene Klasse zu verschieben.

Also, wenn der Fehler auftritt

xxx ist keine einschließende Klasse

Sie können es auf eine der folgenden Arten lösen:

  • Ergänzen Sie die static Schlüsselwort zur inneren Klasse hinzu, oder
  • Verschieben Sie es in eine eigene Klasse.

1

Wenn die übergeordnete Klasse Singleton ist, gehen Sie wie folgt vor:

Parent.Child childObject = (Parent.getInstance()).new Child();

Dabei getInstance()wird das Singleton-Objekt der übergeordneten Klasse zurückgegeben.


0

Um die Anforderung aus der Frage zu erfüllen, können wir Klassen in die Schnittstelle einfügen:

public interface Shapes {
    class AShape{
    }
    class ZShape{
    }
}

und dann als zuvor versuchter Autor verwenden:

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

Wenn wir nach der richtigen "logischen" Lösung suchen, sollte ein fabricEntwurfsmuster verwendet werden

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.