classe interna em relação vs em sala de aula
-
12-09-2019 - |
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.
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