Non è una classe acclusa Java


366

Sto cercando di creare un gioco Tetris e sto ricevendo l'errore del compilatore

Shape is not an enclosing class

quando provo a creare un oggetto

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

Sto usando le classi interne per ogni forma. Ecco parte del mio codice

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

Che cosa sto facendo di sbagliato ?


160
new Shape().new ZShape();. La classe ZShapenecessita di un'istanza chiusa per essere istanziata.
Sotirios Delimanolis,

4
sposta la classe interna in un file separato
Dimmduh

Il commento di @Dimmduh dovrebbe essere la risposta in questo caso. Non dovrebbero essere classi interiori. Spostandoli si identificherebbero gli altri problemi con la classe Shape esistenti.
Jeremiah Adams,

Non per rispondere alla domanda qui, ma posso suggerire di usare l' ereditarietà qui dove AShapeed ZShapeestendere la classe base Shapes. Le classi di nidificazione non sono un ottimo progetto per questo problema.
Paramvir Singh Karwal,

Risposte:


492

ZShape non è statico, quindi richiede un'istanza della classe esterna.

La soluzione più semplice è creare ZShape e qualsiasi classe nidificata, staticse possibile.

Vorrei anche fare qualsiasi campo finalo static finalche tu possa pure.


13
Fare ZShape staticsconfigge totalmente lo scopo di ciò che sta cercando di fare, di cui è un'istanza una copia ZShape.
Cardano,

17
@Cardano rendendolo staticpiù semplice, non più difficile.
Peter Lawrey,

12
un'altra soluzione semplice è quella di rendere la classe racchiude un'istanza della classe interna, cioè ottenendo ZShape questo modo: ZShape myShape = new Shape().instantiateZShape();. Implica che la ZShape che ottieni non esiste senza una Shape, che è l'intento qui.
Vince il

@Peter Lawrey Come ti sei reso conto che tutte le istanze Shape devono usare lo stesso ZShape? Non capisco dalla sua fonte.
L'incredibile gennaio

2
Ci sono 2 casi se vogliamo statica o un'istanza. Renderlo statico non aiuterà sempre.
Yogesh Chuahan,

177

Supponiamo che RetailerProfileModel sia la tua classe principale e RetailerPaymentModel sia una classe interna al suo interno. È possibile creare un oggetto della classe Inner all'esterno della classe come segue:

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

34
Questa risposta è stata davvero utile, non ho mai saputo che potevi chiamare nuovo due volte di seguito (e ho fatto java per 8+ anni!)
PaulBGD

1
Puoi sicuramente chiamare un nuovo operatore un numero qualsiasi di volte fino a quando non vuoi mantenere un riferimento a quell'oggetto.
Vishal Kumar,

1
Se un oggetto della classe interna viene creato in questo modo, come accede ai membri della classe esterna?
Xingang Huang,

1
All'interno della stessa classe interna, puoi usare OuterClass.this.Non credo che ci sia un modo per ottenere l'istanza al di fuori del codice della classe interna. Ovviamente, puoi sempre presentare la tua proprietà: public OuterClass getOuter () {return OuterClass.this; }
Vishal Kumar,

Funziona per i test:underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
felvhage,

48

Quello che suggerirei non è convertire la classe non statica in una classe statica perché in tal caso, la tua classe interna non può accedere ai membri non statici della classe esterna.

Esempio :

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

Quindi, in tal caso, puoi fare qualcosa del tipo:

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

Che dire di Outer.Inner obj = (new Outer) .new Inner ();
Hussain KMR Behestee,

1
@HussainKMRBehestee, no, non funzionerebbe di sicuro. Tuttavia, questo avrebbe funzionatoOuter.Inner obj = new Outer().new Inner();
Amit Upadhyay,

Ma Amit, funziona per me. Mi farebbe piacere se tu potessi spiegare perché non dovrebbe funzionare.
Hussain KMR Behestee,

1
@HussainKMRBehestee, spiegazione: posso solo supporre che la grammatica in Java dice che per creare un'istanza di una classe dobbiamo chiamare il costruttore, e mentre si chiama il costruttore ()è obbligatorio. Tuttavia, C, C ++ non è un must. Ecco un esempio che non funziona. Inoltre, ho trovato questo post . che sta spiegando di più sulla grammatica in Java e su come vengono analizzati. Mi piacerebbe vedere un caso esemplificativo quando questa sintassi funziona per te.
Amit Upadhyay,

1
Oh, mio ​​cattivo, era un refuso, Outer.Inner obj = (new Outer ()). New Inner (); spero che questa volta sia ok e grazie per averlo notato.
Hussain KMR Behestee,

18

Come indicato nei documenti :

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
Muhammad Omer Aslam,

Grazie! Ho appena iniziato.
Brennan Miller,

10

A volte, dobbiamo creare una nuova istanza di una classe interna che non può essere statica perché dipende da alcune variabili globali della classe genitore. In tale situazione, se si tenta di creare l'istanza di una classe interna non statica, not an enclosing classviene generato un errore.

Prendendo l'esempio della domanda, cosa succede se ZShapenon può essere statico perché necessita di una variabile di Shapeclasse globale ?

Come puoi creare una nuova istanza di ZShape? Questo è come:

Aggiungi un getter nella classe genitore:

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

Accedilo in questo modo:

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


1

Ho riscontrato lo stesso problema. Ho risolto creando un'istanza per ogni classe pubblica interna. per quanto riguarda la tua situazione, ti suggerisco di usare l'eredità diversa dalle classi interne.

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
}

allora puoi new Shape (); e visita ZShape attraverso shape.zShape;


1
Una soluzione sbagliata Errore logico. Se la classe interna (ad es. ZShape) richiede di impostare un campo, nel costruttore della classe esterna devi ottenerlo! public Shape (String field1_innerClass, int field2_innerClass ...) {zShape = new ZShape (String field1_innerClass, int field2_innerClass ...) ...}}
Mohsen Abasi,

1

Non è necessario rendere la classe nidificata come statica ma deve essere pubblica

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

1

Una cosa che all'inizio non ho capito quando ho letto la risposta accettata è che rendere statica una classe interna è praticamente la stessa cosa che spostarla in una classe separata.

Pertanto, quando si ottiene l'errore

xxx non è una classe chiusa

Puoi risolverlo in uno dei seguenti modi:

  • Aggiungi la staticparola chiave alla classe interna o
  • Spostalo nella sua classe separata.

1

Nel caso in cui la classe Parent sia singleton, utilizzare la seguente modalità:

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

dove getInstance()restituirà l'oggetto singleton della classe genitore.


0

Per raggiungere il requisito dalla domanda, possiamo mettere le classi in interfaccia:

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

e quindi utilizzare come autore provato prima:

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

Se stiamo cercando la corretta soluzione "logica", dovrebbe essere utilizzato il fabricmodello di progettazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.