java - una - Clase interna en interfaz vs en clase
pildorasinformaticas java swing (6)
En mi humilde opinión, la ventaja es que tienes menos clases que saturan la carpeta de tu proyecto si son triviales; La desventaja es que cuando su clase interna crece a lo largo del cambio de requisitos, el mantenimiento se convierte en su pesadilla.
¿Cuál es la diferencia entre estas dos declaraciones dentro de la clase? 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 caso 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 realizada: a la colocación del método getvalue.
más información: soy capaz de crear una instancia de la clase de elementos 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();
}
Dado que no se crea una instancia de una interfaz, se puede acceder a todos los elementos dentro de una interfaz mediante la notación de puntos sin que se haya creado una instancia de la interfaz LEVELS simplemente porque no puede crear una instancia de una interfaz; de hecho, una clase definida dentro de una interfaz es permeable a la referencia estática.
Decir que la clase de Artículos en el caso B no es estática no tiene sentido. Dado que ambos casos, A y B, están instanciados de la misma manera, no estoy buscando semántica sobre lo que es estático o interno o anidado. Deja de darme respuestas sobre la semántica. Quiero las diferencias / ventajas del compilador, el tiempo de ejecución y el comportamiento, o si no lo hay, dígalo. No más respuestas sobre la semántica por favor !!!!! Un experto en las especificaciones de JVM o .NET VM especifique esta pregunta de respuesta en lugar de los libros de texto semánticos.
Las clases internas estáticas son en su mayoría similares a las clases de nivel superior, excepto que la clase interna tiene acceso a todas las variables y métodos estáticos de la clase adjunta. El nombre de la clase adjunta se agrega efectivamente al espacio de nombres del paquete de la clase interna. Al declarar una clase como una clase interna estática, está comunicando que la clase está inseparablemente ligada al contexto de la clase adjunta.
Las clases internas no estáticas son menos comunes. La principal diferencia es que las instancias de una clase interna no estática contienen una referencia implícita a una instancia de la clase envolvente y, como resultado, tienen acceso a las variables de la instancia y los métodos de esa instancia de la clase envolvente. Esto lleva a algunos modismos de instanciación de aspecto extraño, 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();
Las clases internas no estáticas están mucho más íntimamente ligadas a sus clases adjuntas que las clases internas estáticas. Tienen usos válidos (por ejemplo, los iteradores a menudo se implementan como clases internas no estáticas dentro de la clase de la estructura de datos sobre la que se iteran).
Es un error común declarar una clase interna no estática cuando realmente solo necesitas el comportamiento de la clase interna estática.
Los ejemplos que da de clases anidadas / internas son malos ejemplos (IMO). Además, el segundo ejemplo no es válido en Java, ya que una interfaz solo puede declarar (implícitamente) 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(...);
}
Al incorporar la clase de Respuesta, estamos indicando que es una parte fundamental de la API del Trabajador sin otros usos.
La clase Map.Entry es un ejemplo bien conocido de este idioma.
Pensé que el primero declararía una clase de niveles y una clase interna estática llamada Items. Los artículos podrían ser referenciados por Levels.Items y serían estáticos.
Mientras que el segundo declararía una clase interna simple, a la que se puede acceder mediante Levels.Items, como en el siguiente:
Levels.Items hello = new Levels.Items();
EDIT: esto es totalmente incorrecto, lea los comentarios y otras respuestas.
Si declara una clase anidada en una interfaz, siempre es pública y estática . Asi que:
public interface Levels{
class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
Es exactamente lo mismo que
public interface Levels{
public static class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
E incluso
public interface Levels{
static class Items {
public String value;
public String path;
public String getValue() {return value;}
}
}
He comprobado esto con javap -verbose y todos 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;
}
Una clase interna static
es una clase anidada, y la no estática se llama una clase interna. Para más, mira aquí .
Sin embargo, me gusta citar un extracto del mismo enlace.
Una clase anidada estática interactúa con los miembros de la instancia de su clase externa (y otras clases) al igual que cualquier otra clase de nivel superior. En efecto, una clase anidada estática es conductualmente una clase de nivel superior que se ha anidado en otra clase de nivel superior para conveniencia de empaquetado.
No usaste la palabra static
en el segundo caso. Y crees que sería implícitamente static
porque es una interfaz. Tienes razón al asumir eso.
Puede crear una instancia de la clase interna en su interfaz, al igual que una clase anidada estática, porque en realidad es una clase anidada static
.
Levels.Items hello = new Levels.Items();
Por lo tanto, la declaración anterior será válida en ambos casos . Su primer caso es de clase anidada estática, y en el segundo caso no especificó static
, pero incluso entonces sería una clase anidada estática porque está en la interfaz. Por lo tanto, no hay otra diferencia que el hecho de que uno está anidado en una clase y el otro en una interfaz .
Normalmente, una clase interna en una clase, no en la interfaz , se ejemplificaría como a continuación.
Levels levels = new Levels();
Levels.Items items = levels.new Items();
Además, una clase interna "no estática" tendrá una referencia implícita a su clase externa. Este no es el caso de la clase anidada "estática".