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 ?

V Sebi
quelle
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.

Peter Lawrey
quelle
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();
Vishal Kumar
quelle
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();
Amit Upadhyay
quelle
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
18

Wie in den Dokumenten angegeben :

OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Brennan Miller
quelle
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Aus dem Rückblick
Muhammad Omer Aslam
Vielen Dank! Ich fange jetzt an.
Brennan Miller
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();
M9J_cfALt
quelle
6
Shape shape = new Shape();
Shape.ZShape zshape = shape.new ZShape();
Антон Лялин
quelle
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;


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

Code
quelle
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

Reishin
quelle