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.

¿Fue útil?

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

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top