Estaba buscando en el código Java para LinkedList
y se dio cuenta de que hacía uso de una clase anidada estática, Entry
.
public class LinkedList<E> ... {
...
private static class Entry<E> { ... }
}
¿Cuál es la razón para usar una clase anidada estática, en lugar de una clase interna normal?
La única razón por la que se me ocurrió fue que Entry no tiene acceso a las variables de instancia, por lo que desde el punto de vista de OOP tiene una mejor encapsulación.
Pero pensé que podría haber otras razones, tal vez el rendimiento. ¿Qué puede ser?
Nota. Espero tener mis términos correctos, lo habría llamado una clase interna estática, pero creo que esto está mal: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
Respuestas:
La página de Sun a la que se vincula tiene algunas diferencias clave entre los dos:
No es necesario
LinkedList.Entry
ser una clase de nivel superior, ya que solo la utilizanLinkedList
(hay algunas otras interfaces que también tienen clases anidadas estáticas denominadasEntry
, comoMap.Entry
- mismo concepto). Y dado que no necesita acceso a los miembros de LinkedList, tiene sentido que sea estático: es un enfoque mucho más limpio.Como señala Jon Skeet , creo que es una mejor idea si está utilizando una clase anidada para comenzar siendo estática, y luego decidir si realmente necesita ser no estática en función de su uso.
fuente
#comment113712_253507
A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class
¿Cómo es eso posible si solo un párrafo antes de los documentos dice que:Static nested classes do not have access to other members of the enclosing class
Tal vez les gustaría decir:A nested (non-static) class interacts with the instance members of its outer class (and other classes) just like any other top-level class
An inner class interacts with the instance members through an implicit reference to its enclosing class
y esto señala otra propiedad interesante denon-static inner classes
asanonymous inner classes
o orlocal classes defined inside a block
: no todos pueden tener unno-arg
constructor porque el compilador antepondrá implícitamente la secuencia arg de cada constructor para pasar una referencia de una instancia del cerramiento clase. Bastante simple.En mi opinión, la pregunta debería ser al revés cada vez que veas una clase interna: ¿ realmente necesita ser una clase interna, con la complejidad adicional y la referencia implícita (en lugar de explícita y más clara, IMO) a una instancia de la clase que lo contiene?
Eso sí, soy parcial como un fanático de C #: C # no tiene el equivalente de las clases internas, aunque sí tiene tipos anidados. No puedo decir que me haya perdido las clases internas todavía :)
fuente
Hay problemas de retención de memoria no obvios a tener en cuenta aquí. Dado que una clase interna no estática mantiene una referencia implícita a su clase 'externa', si una instancia de la clase interna está fuertemente referenciada, entonces la instancia externa también está fuertemente referenciada. Esto puede conducir a rascarse la cabeza cuando la clase externa no se recolecta basura, aunque parece que nada hace referencia a ella.
fuente
Bueno, por un lado, las clases internas no estáticas tienen un campo oculto adicional que apunta a la instancia de la clase externa. Entonces, si la clase Entry no fuera estática, además de tener acceso que no necesita, llevaría alrededor de cuatro punteros en lugar de tres.
Como regla, diría que si define una clase que básicamente está ahí para actuar como una colección de miembros de datos, como una "estructura" en C, considere hacerlo estático.
fuente
La clase interna estática se usa en el patrón de construcción. La clase interna estática puede crear una instancia de su clase externa que solo tiene un constructor privado. Por lo tanto, puede usar la clase interna estática para crear instancias de la clase externa que solo tiene un constructor privado. No puede hacer lo mismo con la clase interna ya que necesita tener un objeto de la clase externa creado antes de acceder a la clase interna.
Esto generará x: 1
fuente
La clase anidada estática es como cualquier otra clase externa, ya que no tiene acceso a los miembros de la clase externa.
Solo por conveniencia de empaque podemos agrupar las clases anidadas estáticas en una clase externa para fines de legibilidad. Aparte de esto, no hay otro caso de uso de clase anidada estática.
Ejemplo para este tipo de uso, puede encontrarlo en el archivo Android R.java (recursos). La carpeta Res de Android contiene diseños (que contienen diseños de pantalla), carpeta dibujable (que contiene imágenes utilizadas para el proyecto), carpeta de valores (que contiene constantes de cadena), etc.
Como todas las carpetas son parte de la carpeta Res, la herramienta de Android genera un archivo R.java (recursos) que contiene internamente muchas clases anidadas estáticas para cada una de sus carpetas internas.
Aquí está la apariencia del archivo R.java generado en Android: aquí se usan solo para la comodidad del empaque.
fuente
De http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :
fuente
Ejemplo simple:
Si no es estática, la clase no se puede instanciar exept en una instancia de la clase superior (así que no en el ejemplo donde main es una función estática)
fuente
Una de las razones para estática vs. normal tiene que ver con la carga de clases. No puede crear una instancia de una clase interna en el constructor de su padre.
PD: Siempre he entendido que 'anidado' e 'interno' son intercambiables. Puede haber sutiles matices en los términos, pero la mayoría de los desarrolladores de Java lo entenderían.
fuente
Las clases internas no estáticas pueden provocar pérdidas de memoria, mientras que la clase interna estática protegerá contra ellas. Si la clase externa contiene datos considerables, puede reducir el rendimiento de la aplicación.
fuente
No sé acerca de la diferencia de rendimiento, pero como usted dice, la clase anidada estática no es parte de una instancia de la clase adjunta. Parece simplemente más simple crear una clase anidada estática a menos que realmente necesites que sea una clase interna.
Es un poco como por qué siempre hago que mis variables sean definitivas en Java: si no son definitivas, sé que hay algo divertido que sucede con ellas. Si usa una clase interna en lugar de una clase anidada estática, debería haber una buena razón.
fuente
El uso de una clase anidada estática en lugar de una no estática puede ahorrar espacios en algunos casos. Por ejemplo: implementar un
Comparator
dentro de una clase, por ejemplo, Estudiante.Luego,
static
garantiza que la clase de Alumno tenga un solo Comparador, en lugar de crear una instancia nueva cada vez que se crea una nueva instancia de alumno.fuente
Una ventaja de la clase interna
Sin existir de clase externa, la clase interna no existirá.
Hay cuatro tipos de clase interna.
punto ---
para invocar la clase interna normal en el área estática de la clase externa.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
para invocar la clase interna normal en el área de instancia de la clase externa.
Inner i=new Inner();
para invocar la clase interna normal fuera de la clase externa.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
inside Inner class Este puntero a la clase interna.
this.member-current inner class outerclassname.this--outer class
para el modificador aplicable de la clase interna es - public, default,
final,abstract,strictfp,+private,protected,static
external $ inner es el nombre del nombre de la clase interna.
clase interna dentro del método de instancia, entonces podemos acceder al campo estático y de instancia de clase externa
10. clase interna dentro del método estático, entonces solo podemos acceder al campo estático de
clase exterior
fuente