son - static int java
Clase anidada estática en Java, ¿por qué? (13)
Adavantage de clase interna--
- un solo uso
- admite y mejora la encapsulación
- legibilidad
- acceso privado al campo
Sin existencia de clase interna, la clase interna no existirá.
class car{
class wheel{
}
}
Hay cuatro tipos de clase interna.
- clase interna normal
- Método Clase interna local
- Clase interna anónima
- clase interna estática
punto ---
- desde la clase interna estática, solo podemos acceder al miembro estático de la clase externa.
- Dentro de la clase interna no podemos declarar miembro estático.
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 a la clase interna normal fuera de la clase externa.
Outer 0=new Outer(); Outer.Inner i= O.new Inner();
inside Clase interna Este puntero a la clase interna.
this.member-current inner class outerclassname.this--outer class
para el modificador aplicable de la clase interna es - público, por defecto,
final,abstract,strictfp,+private,protected,static
outer $ 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 e instancia de la clase externa.
10. clase interna dentro del método estático, entonces podemos acceder solo al campo estático de
clase exterior
class outer{
int x=10;
static int y-20;
public void m1() {
int i=30;
final j=40;
class inner{
public void m2() {
// have accees x,y and j
}
}
}
}
Estaba mirando el código de Java para LinkedList
y noté 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 podía pensar, era 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é podría ser?
Nota. Espero tener mis términos correctos, lo habría llamado una clase interna estática, pero creo que esto es incorrecto: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
Bueno, para empezar, 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 era estática, además de tener acceso que no necesita, llevaría cuatro punteros en lugar de tres.
Como regla general, 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 la posibilidad de hacerla estática.
Desde http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html :
Utilice una clase anidada no estática (o clase interna) si necesita acceder a los campos y métodos no públicos de una instancia envolvente. Use una clase anidada estática si no necesita este acceso.
Ejemplo simple:
package test;
public class UpperClass {
public static class StaticInnerClass {}
public class InnerClass {}
public static void main(String[] args) {
// works
StaticInnerClass stat = new StaticInnerClass();
// doesn''t compile
InnerClass inner = new InnerClass();
}
}
Si no es estática, la clase no se puede instanciar excepto en una instancia de la clase superior (por lo tanto, no en el ejemplo donde main es una función estática)
En mi opinión, la pregunta debería ser al revés cada vez que vea 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 contenedora?
Eso sí, estoy predispuesto como fanático de C #: C # no tiene el equivalente de clases internas, aunque sí tiene tipos anidados. No puedo decir que aún me haya perdido las clases internas :)
Hay problemas de retención de memoria no obvios para tener en cuenta aquí. Como 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 se referencia fuertemente. Esto puede ocasionar algunos arañazos en la cabeza cuando la clase externa no es basura, aunque parece que nada hace referencia a ella.
La clase estática anidada es como cualquier otra clase externa, ya que no tiene acceso a los miembros de la clase externa.
Solo por la conveniencia del empaque, podemos agrupar 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 ese tipo de uso, puedes 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 las imágenes utilizadas para el proyecto), carpeta de valores (que contiene constantes de cadena), etc.
Dado que todas las carpetas son parte de la carpeta Res, la herramienta de Android genera un archivo R.java (recursos) que internamente contiene muchas clases anidadas estáticas para cada una de sus carpetas internas.
Aquí está el aspecto del archivo R.java generado en Android: Aquí lo usan solo para la conveniencia del empaquetado.
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.techpalle.b17_testthird;
public final class R {
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class layout {
public static final int activity_main=0x7f030000;
}
public static final class menu {
public static final int main=0x7f070000;
}
public static final class string {
public static final int action_settings=0x7f050001;
public static final int app_name=0x7f050000;
public static final int hello_world=0x7f050002;
}
}
La clase interna estática se usa en el patrón del constructor. La clase interna estática puede crear una instancia de su clase externa que solo tiene un constructor privado. De modo que puede usar una clase interna estática para instanciar 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 creada antes de acceder a la clase interna.
class OuterClass {
private OuterClass(int x) {
System.out.println("x: " + x);
}
static class InnerClass {
public static void test() {
OuterClass outer = new OuterClass(1);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass.InnerClass.test();
// OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
}
}
Esto generará x: 1
La página de Sun a la que se vincula tiene algunas diferencias clave entre los dos:
Una clase anidada es un miembro de su clase adjunta. Las clases anidadas no estáticas (clases internas) tienen acceso a otros miembros de la clase adjunta, incluso si se declaran privadas. Las clases anidadas estáticas no tienen acceso a otros miembros de la clase adjunta.
...Nota: 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 ha sido anidada en otra clase de nivel superior para conveniencia de empaquetado.
No es necesario que LinkedList.Entry
sea una clase de nivel superior, ya que solo la utiliza LinkedList
(existen otras interfaces que también tienen clases anidadas estáticas llamadas Entry
, como Map.Entry
- same concept). Y como no necesita acceder 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ás utilizando una clase anidada es comenzar con que es estática, y luego decidir si realmente necesita ser no estática según tu uso.
Las clases internas no estáticas pueden provocar fugas 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.
No sé sobre la diferencia de rendimiento, pero como dices, la clase anidada estática no forma parte de una instancia de la clase adjunta. Parece más simple crear una clase anidada estática a menos que realmente necesite 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 pasa algo raro con ellas. Si usa una clase interna en lugar de una clase anidada estática, debería haber una buena razón.
Una de las razones de la estática frente a la normal tiene que ver con la carga de clases. No puede instanciar 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 también lo entenderían.
Usar una clase anidada estática en lugar de no estática puede ahorrar espacios en algunos casos. Por ejemplo: implementar un Comparator
dentro de una clase, decir Estudiante.
public class Student {
public static final Comparator<Student> BY_NAME = new ByName();
private final String name;
...
private static class ByName implements Comparator<Student> {
public int compare() {...}
}
}
Luego, la static
garantiza que la clase de Estudiante tenga solo un Comparador, en lugar de crear una instancia nueva cada vez que se crea una nueva instancia de estudiante.