clase interna en la interfaz en la clase vs
-
12-09-2019 - |
Pregunta
¿Cuál es la diferencia entre estas dos declaraciones innerclass? También comentar sobre ventajas / desventajas?
caso A:. Clase dentro de una clase
public class Levels {
static public class Items {
public String value;
public String path;
public String getValue() {
return value;}
}
}
y la caja B:. Clase dentro de la interfaz
public interface Levels{
public class Items {
public String value;
public String path;
public String getValue() {
return value;}
}
}
corrección efectuada:. A la colocación del método getValue
Más información: Soy capaz de crear una instancia de la clase de artículos, tanto en los casos A y B en otra clase que no implementa la interfaz en absoluto.
public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
Levels.Items items = new Levels.Items();
}
Desde una interfaz no se instancia, todos los elementos dentro de una interfaz son accesibles por la notación de punto sin interfaz NIVELES instanciado simplemente porque no se puede instanciar una interfaz -. Hacer efectiva una clase definida en el interior de una interfaz permeable a la referencia estática
Así que decir que clase de artículos en el caso B no es estática, no tiene sentido. Dado que tanto los casos A y B se crean instancias de la misma manera, yo no busco a la semántica de lo que es estático o interna o anidada. Deja de dar respuestas en la semántica. Quiero que el compilador, tiempo de ejecución y las diferencias de comportamiento / ventajas, o si ninguno entonces dilo. No más respuestas sobre la semántica por favor !!!!! Un experto en la JVM o .NET VM entrañas de especificación favor respuesta a esta pregunta en lugar de semanticissiests de libros de texto.
Solución
clases internas estáticas son en su mayoría similar a clases de nivel superior, a excepción de la clase interna tiene acceso a todos los estáticas variables y métodos de la clase envolvente. El nombre de clase envolvente se anexa eficazmente para el espacio de nombres de envase de la clase interna. Al declarar una clase como una clase interna estática, se está comunicando que la clase de alguna manera está inseparablemente vinculada con el contexto de la clase envolvente.
clases internas no estáticos son menos comunes. La diferencia principal es que las instancias de una clase interna no estática contener una referencia implícita a una instancia de la clase envolvente, y como resultado tienen acceso a las variables y los métodos de esa instancia clase envolvente de instancia. Esto lleva a algunos modismos de instancias aspecto raro, por ejemplo:
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();
No-estática clases internas son mucho más íntimamente ligadas a sus clases de cerramiento que las clases internas estáticas. Ellos tienen usos válido (por ejemplo iteradores a menudo se implementan como clases internas no estáticos dentro de la clase de la estructura de datos que iterar sobre).
Es un error común para declarar una clase interna no estática cuando sólo se necesita realmente el comportamiento de la clase interna estática.
Otros consejos
Una clase interna static
es una clase anidada, y la no estático se llama una clase interna. Para más información, mira aquí .
Sin embargo, me gusta citar un extracto del mismo enlace.
Una clase anidada estática interactúa con los miembros de instancia de su exterior clase (y otras clases) al igual cualquier otra clase de nivel superior. En efecto, una clase anidada estática es conductualmente una clase de nivel superior que ha sido anidado en otra clase de nivel superior para envases conveniencia.
No usó la palabra static
en el segundo caso. Y le parece que implícitamente se static
porque su interfaz. Estás justo en el supuesto de que.
Puede crear una instancia de la clase interna en su interfaz, al igual que una clase anidada estática, porque realmente es un static
anidado clase.
Levels.Items hello = new Levels.Items();
Por lo tanto, la afirmación anterior será válido en ambos de sus casos . Su primer caso es de clase anidada estática, y en el segundo caso no se hayan indicado static
, pero incluso entonces sería una clase anidada estática porque está en el interfaz. Por lo tanto, no hay diferencia otra, entonces el hecho de que uno está anidada en una clase, y el otro en una interfaz .
normalmente una clase interna en una clase, no en la interfaz , habría ser instanciado como a continuación.
Levels levels = new Levels();
Levels.Items items = levels.new Items();
Además, una clase interna "no estático" tendrá una referencia implícita a su clase externa. Este no es el caso con la clase anidada "estática".
Si se declara una clase anidada en una interfaz siempre es público y estática . Por lo tanto:
public interface Levels{
class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
es exactamente el mismo que
public interface Levels{
public static class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
Y aun
public interface Levels{
static class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
He comprobado esto con -verbose javap y todos ellos producen
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;
}
Los ejemplos que das de clases anidadas / interno (OMI) son malos ejemplos. Además del segundo ejemplo no es válido de Java desde una interfaz sólo puede declarar (implícitamente) los métodos abstractos. Aquí hay un mejor ejemplo:
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(...);
}
Mediante la integración de la clase de respuesta, estamos indicando que es una parte fundamental de la API trabajador sin otros usos.
La clase Map.Entry es un ejemplo bien conocido de este idioma.
En mi humilde opinión, ventaja es que tienes menos clases que saturan su carpeta de proyecto si son triviales; desventaja es que cuando su clase interna llegar creciente a lo largo del requisito de cambio, la maintenacne convertirse en su pesadilla.
pensé que la primera sería declarar un nivel de grupo y una clase interna estática denominada Elementos. Los productos que pueden ser referenciados por Levels.Items y sería estática.
Mientras que el segundo sería declarar una clase interna simple, que se puede acceder mediante el uso de Levels.Items, como en lo siguiente:
Levels.Items hello = new Levels.Items();
EDIT: esto es totalmente erróneo, lee los comentarios y otras respuestas
.