Não é uma classe anexa Java


366

Estou tentando criar um jogo Tetris e estou recebendo o erro do compilador

Shape is not an enclosing class

quando tento criar um objeto

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

Estou usando classes internas para cada forma. Aqui está parte do meu código

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

O que estou fazendo errado ?


160
new Shape().new ZShape();. A classe ZShapeprecisa de uma instância envolvente para ser instanciada.
Sotirios Delimanolis 27/11

4
mover classe interna para arquivo separado
Dimmduh

O comentário @Dimmduh deve ser a resposta neste caso. Eles não devem ser classes internas. Movê-los identificaria os outros problemas com a classe Shape que existem.
Jeremias Adams

Não para responder à pergunta aqui, mas posso sugerir usar herança aqui, onde AShapee ZShapeestender a classe base Shapes. Aninhar classes não é um design muito bom para esse problema.
Paramvir Singh Karwal

Respostas:


492

ZShape não é estático, portanto, requer uma instância da classe externa.

A solução mais simples é criar o ZShape e qualquer classe aninhada, staticse possível.

Eu também faria quaisquer campos finalou static finalque você possa também.


13
Tornar ZShape statictotalmente derrota o propósito do que ele está tentando fazer, que é instanciar uma cópia ZShape.
Cardano

17
A @Cardano statictorna isso mais fácil, não mais difícil.
Peter Lawrey

12
outra solução simples é fazer com que a classe instanciar encerrando a classe interna, ou seja, recebendo ZShape desta forma: ZShape myShape = new Shape().instantiateZShape();. Isso implica que o ZShape que você obtém não existe sem um Shape, que é a intenção aqui.
Vince

@ Peter Lawrey Como você percebeu que todas as instâncias do Shape precisam usar o mesmo ZShape? Eu não entendo da fonte dele.
O incrível Jan

2
Existem 2 casos, se queremos estática ou uma instância. Tornar estático não ajudará sempre.
Yogesh Chuahan

177

Suponha que RetailerProfileModel seja sua classe Principal e RetailerPaymentModel seja uma classe interna. Você pode criar um objeto da classe Inner fora da classe da seguinte maneira:

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

34
Essa resposta foi realmente útil, eu nunca soube que você poderia chamar de novo duas vezes seguidas (e eu fiz java para 8 + anos!)
PaulBGD

11
Você certamente pode chamar um novo operador várias vezes até não desejar manter uma referência a esse objeto.
Vishal Kumar

11
Se um objeto da classe interna é criado dessa maneira, como ele acessa os membros da classe externa?
Xingang Huang 22/09

11
Dentro da própria classe interna, você pode usar OuterClass.this. Porém, não acho que exista uma maneira de obter a instância de fora do código da classe interna. Obviamente, você sempre pode apresentar sua própria propriedade: public OuterClass getOuter () {return OuterClass.this; }
Vishal Kumar

Trabalhos para testes:underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
felvhage

48

O que eu sugeriria não é converter a classe não estática em uma classe estática porque, nesse caso, sua classe interna não pode acessar os membros não estáticos da classe externa.

Exemplo:

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

Portanto, nesse caso, você pode fazer algo como:

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

E quanto a Outer.Inner obj = (novo Outer) .new Inner ();
Hussain KMR Behestee

11
@HussainKMRBehestee, não, isso não funcionaria com certeza. No entanto, isso iria funcionarOuter.Inner obj = new Outer().new Inner();
Amit Upadhyay

Mas Amit, funciona para mim. Ficaria feliz se você pudesse explicar por que não deve funcionar.
Hussain KMR Behestee

11
@HussainKMRBehestee, explicação: Só posso adivinhar que a gramática em Java diz que, para instanciar uma classe, precisamos chamar o construtor, e ao mesmo tempo em que chama o construtor ()é obrigatório. No entanto, C, C ++ não é obrigatório. Aqui está um exemplo que não funciona. Além disso, eu encontrei este post . que explica mais sobre gramática em Java e como elas são analisadas. Eu adoraria ver um exemplo de caso quando essa sintaxe estiver funcionando para você.
Amit Upadhyay

11
Ah, que pena, foi um erro de digitação, Outer.Inner obj = (new Outer ()). New Inner (); Espero que desta vez esteja tudo bem e obrigado por perceber isso.
Hussain KMR Behestee

18

Conforme declarado nos documentos :

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

Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada. - Da avaliação
Muhammad Omer Aslam

Obrigado! Apenas começando.
Brennan Miller

10

Às vezes, precisamos criar uma nova instância de uma classe interna que não possa ser estática, pois depende de algumas variáveis ​​globais da classe pai. Nessa situação, se você tentar criar a instância de uma classe interna que não é estática, not an enclosing classserá gerado um erro.

Tomando o exemplo da pergunta, e se ZShapenão puder ser estático, porque precisa de variável global de Shapeclasse?

Como você pode criar uma nova instância de ZShape? É assim:

Adicione um getter na classe pai:

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

Acesse-o assim:

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


1

Eu encontrei o mesmo problema. Eu resolvi criando uma instância para cada classe pública interna. quanto à sua situação, sugiro que você use outra herança além das classes internas.

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
}

então você pode novo Shape (); e visite o ZShape através de shape.zShape;


11
Uma solução errada. Erro lógico. Se a classe interna (por exemplo, ZShape) exigir que qualquer campo seja definido, você deve obtê-lo no construtor da classe externa! public Shape (String field1_innerClass, int field2_innerClass ...) {zShape = new ZShape (String field1_innerClass, int field2_innerClass ...) ...}}
Mohsen Abasi

1

Não há necessidade de tornar a classe aninhada como estática, mas deve ser pública

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

1

Uma coisa que eu não percebi a princípio ao ler a resposta aceita foi que tornar estática uma classe interna é basicamente a mesma coisa que movê-la para sua própria classe separada.

Assim, ao obter o erro

xxx não é uma classe anexa

Você pode resolvê-lo de uma das seguintes maneiras:

  • Adicione a staticpalavra-chave à classe interna ou
  • Mova-o para sua própria classe separada.

1

Caso a classe Parent seja única, use a seguinte maneira:

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

onde getInstance()retornará o objeto singleton da classe pai.


0

Para atingir o requisito da pergunta, podemos colocar classes na interface:

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

e use como autor tentado antes:

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

Se estamos procurando a solução "lógica" adequada, deve ser usado o fabricpadrão de design

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.