Pergunta

Qual é a diferença entre essas duas declarações innerclass? Também comentar sobre vantagens / desvantagens?

Caso A:. Classe dentro de uma classe

public class Levels {   
  static public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

e caso B:. Classe dentro da interface

public interface Levels{

  public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

correção feita:. A colocação de método GetValue

Mais informações: Eu sou capaz de classe Itens instanciar em ambos os casos A e B em outra classe que não implementar a interface AT ALL.

public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
 Levels.Items items = new Levels.Items();
}

Uma vez que uma interface não é instanciado, todos os elementos dentro de uma interface são acessíveis por notação de ponto, sem níveis de interface instanciado simplesmente porque você não pode instanciar uma interface -. Efetivamente tornando uma classe definida dentro de um permeável interface para referência estática

Assim dizendo que itens de classe, no caso B não é estática não faz sentido. Desde ambos os casos A e B são instanciados da mesma forma, não estou à procura de semântica sobre o que é estático ou interior ou aninhadas. Pare de dar-me respostas sobre semântica. Eu quero o compilador, runtime e diferenças comportamentais / vantagens, ou se nenhum, em seguida, que o diga. Não há mais respostas sobre a semântica agradar !!!!! Um especialista em JVM ou .NET VM entranhas especificação agradar esta pergunta de resposta em vez de semanticissiests livro de texto.

Foi útil?

Solução

estáticos classes internas são na sua maioria semelhantes às classes de nível superior, exceto a classe interna tem acesso a todo o estática variáveis ??e métodos da classe de fechamento. O nome de classe envolvente é efectivamente apenso ao espaço de nomes pacote da classe interna. Ao declarar uma classe como uma classe interna estática, você está se comunicando que a classe é de alguma forma inseparavelmente ligada ao contexto da classe delimitador.

classes internas não-estáticos são menos comuns. A principal diferença é que instâncias de uma classe não-estática interior conter uma referência implícita a uma instância da classe envolvente, e como resultado, têm acesso a variáveis ??e métodos de instância de classe que encerra instância. Isto leva a algumas estranhas expressões idiomáticas instanciação que procuram, por exemplo:

Levels levels = new Levels(); // first need an instance of the enclosing class

// The items object contains an implicit reference to the levels object
Levels.Items items  = levels.new Items(); 

classes internas não-estáticos são muito mais intimamente ligada às suas aulas envolventes do que classes internas estáticas. Eles têm usos válidos (por exemplo, iteradores são freqüentemente implementados como classes internas não-estáticos dentro da classe da estrutura de dados que iterar).

É um erro comum para declarar uma classe interna não-estática quando você só precisa realmente o comportamento classe interna estática.

Outras dicas

Um static classe interna é uma classe aninhada, eo non-static é chamado de uma classe interna. Para mais, olhar aqui .

No entanto, eu gostaria de citar um excerto do mesmo link.

interage classe aninhados A estática com os membros de instância do seu exterior classe (e outras classes), assim como qualquer outra classe de nível superior. Com efeito, uma classe aninhada estática é comportamentalmente uma classe de nível superior que tem sido aninhados em outra classe de nível superior para embalagem conveniência.

Você não usou a palavra static no segundo caso. E você acha que seria implicitamente static porque sua interface. Você está certo em assumir isso.

Você pode instanciar a classe interna em sua interface, assim como uma classe aninhada estática, porque a sua realmente um static classe aninhada.

Levels.Items hello = new Levels.Items();

Assim, a declaração acima será válida em ambos os casos, . Seu primeiro caso é de classe aninhada estática, e no segundo caso você não especificou static, mas mesmo assim seria uma classe aninhada estática porque a sua na interface. Por isso, nenhuma outra diferença, então o fato de que está aninhado em uma classe, e outro em uma interface .

Normalmente, uma classe interna em uma classe, não em relação , seria instanciado como abaixo.

Levels levels = new Levels();
Levels.Items items = levels.new Items();

Além disso, um "não-estático" classe interna terá uma referência implícita à sua classe externa. Este não é o caso com "estático" classe aninhada.

Se você declarar uma classe aninhada em uma interface é sempre público e estática . Assim:

public interface Levels{
    class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

É exatamente o mesmo que

public interface Levels{
    public static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

E mesmo

public interface Levels{
    static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

Eu verifiquei isso com javap -verbose e eles todos os produtos

Compiled from "Levels.java"
public class Levels$Items extends java.lang.Object
  SourceFile: "Levels.java"
  InnerClass: 
   public #14= #3 of #23; //Items=class Levels$Items of class Levels
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method   #4.#21; //  java/lang/Object."<init>":()V
const #2 = Field    #3.#22; //  Levels$Items.value:Ljava/lang/String;
const #3 = class    #24;    //  Levels$Items
const #4 = class    #25;    //  java/lang/Object
const #5 = Asciz    value;
const #6 = Asciz    Ljava/lang/String;;
const #7 = Asciz    path;
const #8 = Asciz    <init>;
const #9 = Asciz    ()V;
const #10 = Asciz   Code;
const #11 = Asciz   LineNumberTable;
const #12 = Asciz   LocalVariableTable;
const #13 = Asciz   this;
const #14 = Asciz   Items;
const #15 = Asciz   InnerClasses;
const #16 = Asciz   LLevels$Items;;
const #17 = Asciz   getValue;
const #18 = Asciz   ()Ljava/lang/String;;
const #19 = Asciz   SourceFile;
const #20 = Asciz   Levels.java;
const #21 = NameAndType #8:#9;//  "<init>":()V
const #22 = NameAndType #5:#6;//  value:Ljava/lang/String;
const #23 = class   #26;    //  Levels
const #24 = Asciz   Levels$Items;
const #25 = Asciz   java/lang/Object;
const #26 = Asciz   Levels;

{
public java.lang.String value;

public java.lang.String path;

public Levels$Items();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable: 
   line 2: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


public java.lang.String getValue();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   getfield    #2; //Field value:Ljava/lang/String;
   4:   areturn
  LineNumberTable: 
   line 7: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


}

Os exemplos que você dá de classes aninhadas / internos são (IMO) maus exemplos. Além do segundo exemplo não é válido Java desde uma interface só pode declarar (implicitamente) métodos abstratos. Aqui está um exemplo melhor:

public interface Worker {

    public class Response {
        private final Status status;
        private final String message;
        public Response(Status status, String message) {
            this.status = status; this.message = message;
        }
        public Status getStatus() { return status; }
        public String getMessage() { return message; }
    }

    ...

    public Response doSomeOperation(...);
}

Ao incorporar a classe Response, estamos indicando que é uma parte fundamental da API Trabalhador sem outros usos.

A classe Map.Entry é um exemplo bem conhecido desta expressão.

IMHO, vantagem é que você tem menos aulas desordenar sua pasta de projeto se eles estão trivial; desvantagem é que, quando a sua classe interna começa a crescer ao longo da mudança requisito, o maintenacne tornar-se seu pesadelo.

Eu pensei que o primeiro seria declarar uma níveis de classe e uma classe interna estática chamada Items. Itens poderia ser referenciado por Levels.Items e seria estático.

Enquanto o segundo seria declarar uma classe interna simples, que pode ser acessado por usando Levels.Items, como no seguinte:

Levels.Items hello = new Levels.Items();

EDIT:. Isso é totalmente errado, leia os comentários e outras respostas

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top