otra - como instanciar una clase anidada en java
Clase interna de Java y clase anidada estática (24)
Diferencia entre la clase anidada estática y no estática en Java
1) La clase estática anidada no necesita referencia de la clase externa, pero la clase anidada no estática o la clase interna requiere la referencia de la clase externa. No puede crear una instancia de la clase interna sin crear una instancia de la clase externa. Esto es, por mucho, lo más importante a considerar al hacer una clase anidada estática o no estática.
2) la clase estática es en realidad miembro estático de la clase y se puede usar en un contexto estático, por ejemplo, un método estático o un bloque estático de la clase externa.
3) Otra diferencia entre la clase anidada estática y no estática es que no puede acceder a miembros no estáticos, por ejemplo, el método y el campo en la clase estática anidada directamente. Si lo hace, obtendrá un error como "el miembro no estático no se puede utilizar en un contexto estático". Mientras que la clase interna puede acceder a miembros estáticos y no estáticos de la clase externa.
public class OuterClass {
private static String message = "Hello JAVA";
// How to create instance of static and non static nested class
public static void main(String... args) {
// creating instance of nested Static class
InnerClassStatic printer = new InnerClassStatic();
//calling non static method of nested static class
printer.printMessage();
// creating instance of non static nested class or InnerClass class
// In order to create instance of InnerClass class you need an OuterClass class instance
OuterClass outerClass = new OuterClass(); //outerClass class instance for creating non static nested class
InnerClass innerClass = outerClass.new InnerClass();
innerClass.display(); //calling non static method of InnerClass class
// we can also combine above steps in one step to create instance of InnerClass class
InnerClass nonStaticIner = new OuterClass().new InnerClass();
nonStaticIner.display(); // similarly you can now call InnerClass class method
}
// Static nested class
private static class InnerClassStatic {
//Only static member of OuterClass class is directly accessible in nested static class
public void printMessage() {
// Compile time error if message field is not static
System.out.println("Message from nested static class : " + message);
}
}
//non static nested class - also called InnerClass class
private class InnerClass {
// Both static and non static member of OuterClass class is accessible in this InnerClass class
public void display() {
System.out.println(" Message from non static nested or InnerClass class : " + message);
}
}
}
Salida:
Message from nested static class : Hello JAVA
Message from non static nested or Inner class : Hello JAVA
Message from non static nested or Inner class : Hello JAVA
Eso es todo en la diferencia entre la clase anidada estática y no estática en Java. Hasta el momento, solo hemos tocado la clase interna del miembro y no hemos discutido otros dos tipos en la clase interna, por ejemplo, la clase local y la clase interna anónima. En este tutorial de Java, hemos visto qué es la clase estática anidada en Java y cómo crear una instancia de la clase estática y no estática anidada en Java.
En resumen, es fácil crear una instancia de una clase estática anidada, ya que no requiere una instancia de la clase Externa, mientras que una clase no estática estática, por ejemplo, la clase Interna siempre necesitará una instancia de la clase Externa y no puede existir sin una clase Externa Si tiene que elegir entre clase estática y no estática, prefiera la clase anidada estática si puede usar eso.
¿Cuál es la principal diferencia entre una clase interna y una clase anidada estática en Java? ¿El diseño / implementación juega un papel en la elección de uno de estos?
Aquí hay diferencias clave y similitudes entre la clase interna de Java y la clase anidada estática.
¡Espero eso ayude!
Clase interna
- Puede acceder a la clase externa tanto a la instancia como a los métodos y campos estáticos
Asociada con la instancia de la clase adjunta, por lo que para crear una instancia de ella primero se necesita una instancia de la clase externa (observe el nuevo lugar de palabra clave)
Outerclass.InnerClass innerObject = outerObject.new Innerclass();
No se puede definir ningún miembro estático
- No puede tener declaración de clase o interfaz
Clase anidada estática
No se puede acceder a los métodos o campos de instancia de clase externa
No asociado con ninguna instancia de clase adjunta. Para instanciarlo:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Similitudes
- Ambas clases internas pueden acceder incluso a campos privados y métodos de clase externa
- También la clase externa tiene acceso a campos privados y métodos de clases internas.
- Ambas clases pueden tener modificador de acceso privado, protegido o público.
¿Por qué usar clases anidadas?
Según la documentación de Oracle hay varias razones ( documentación completa ):
Es una forma de agrupar lógicamente las clases que solo se usan en un solo lugar: si una clase es útil solo para otra clase, entonces es lógico incrustarla en esa clase y mantenerlas juntas. Anidar tales "clases de ayuda" hace que su paquete sea más ágil.
Aumenta la encapsulación: considere dos clases de nivel superior, A y B, donde B necesita acceso a los miembros de A que de otro modo serían declarados privados. Al ocultar la clase B dentro de la clase A, los miembros de A pueden ser declarados privados y B puede acceder a ellos. Además, B en sí puede esconderse del mundo exterior.
Puede llevar a un código más legible y mantenible: la agrupación de clases pequeñas dentro de las clases de nivel superior coloca el código más cerca de donde se usa.
Clase anidada: clase dentro de clase
Tipos de
- Clase anidada estática
- Clase anidada no estática [clase interna]
Diferencia:
Clase anidada no estática [clase interna]
En la clase anidada no estática, el objeto de la clase interna existe dentro del objeto de la clase externa. De modo que el miembro de datos de la clase externa es accesible a la clase interna. Así que para crear el objeto de la clase interna primero debemos crear el objeto de la clase externa.
outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass();
Clase anidada estática
En la clase estática anidada, el objeto de la clase interna no necesita el objeto de la clase externa, porque la palabra "estática" indica que no es necesario crear el objeto.
class outerclass A {
static class nestedclass B {
static int x = 10;
}
}
Si desea acceder a x, escriba el siguiente método interno
outerclass.nestedclass.x; i.e. System.out.prinltn( outerclass.nestedclass.x);
Creo que la convención que generalmente se sigue es esta:
- clase estática dentro de una clase de nivel superior es una clase anidada
- La clase no estática dentro de una clase de nivel superior es una clase interna , que además tiene dos formas más:
- clase local - clases nombradas declaradas dentro de un bloque como un método o cuerpo de constructor
- Clase anónima : clases sin nombre cuyas instancias se crean en expresiones y declaraciones.
Sin embargo, algunos otros puntos a recordar son:
Las clases de nivel superior y la clase anidada estática son semánticamente iguales, excepto que en el caso de la clase anidada estática, puede hacer referencia estática a campos / métodos estáticos privados de su clase externa [primaria] y viceversa.
Las clases internas tienen acceso a las variables de instancia de la instancia adjunta de la clase [primaria] externa. Sin embargo, no todas las clases internas tienen instancias adjuntas, por ejemplo, las clases internas en contextos estáticos, como una clase anónima utilizada en un bloque de inicializador estático, no lo hacen.
De forma predeterminada, la clase anónima extiende la clase principal o implementa la interfaz principal y no hay más cláusulas para extender ninguna otra clase o implementar más interfaces. Asi que,
-
new YourClass(){};
significaclass [Anonymous] extends YourClass {}
-
new YourInterface(){};
significa que laclass [Anonymous] implements YourInterface {}
-
Siento que la pregunta más grande que permanece abierta, ¿cuál usar y cuándo? Bueno, eso depende principalmente del escenario con el que estés lidiando, pero leer la respuesta dada por @jrudolph puede ayudarte a tomar una decisión.
Creo que ninguna de las respuestas anteriores le explica la diferencia real entre una clase anidada y una clase anidada estática en términos del diseño de la aplicación:
Visión general
Una clase anidada puede ser no estática o estática y en cada caso es una clase definida dentro de otra clase . Una clase anidada debe existir solo para servir es una clase adjunta , si una clase anidada es útil para otras clases (no solo la adjunta), debe declararse como una clase de nivel superior.
Diferencia
Clase anidada no estática : está asociada implícitamente con la instancia adjunta de la clase contenedora, lo que significa que es posible invocar métodos y variables de acceso de la instancia adjunta. Un uso común de una clase anidada no estática es definir una clase de Adaptador.
Clase anidada estática : no puede acceder a la instancia de clase envolvente e invocar métodos en ella, por lo que debe usarse cuando la clase anidada no requiere acceso a una instancia de la clase envolvente. Un uso común de la clase anidada estática es implementar componentes del objeto externo.
Conclusión
Entonces, la principal diferencia entre los dos desde el punto de vista del diseño es que la clase anidada no estática puede acceder a la instancia de la clase contenedora, mientras que la estática no puede .
Desde el Tutorial de Java :
Las clases anidadas se dividen en dos categorías: estáticas y no estáticas. Las clases anidadas que se declaran estáticas se denominan simplemente clases anidadas estáticas. Las clases anidadas no estáticas se denominan clases internas.
Se accede a las clases anidadas estáticas usando el nombre de la clase adjunta:
OuterClass.StaticNestedClass
Por ejemplo, para crear un objeto para la clase anidada estática, use esta sintaxis:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Los objetos que son instancias de una clase interna existen dentro de una instancia de la clase externa. Considera las siguientes clases:
class OuterClass {
...
class InnerClass {
...
}
}
Una instancia de InnerClass puede existir solo dentro de una instancia de OuterClass y tiene acceso directo a los métodos y campos de su instancia adjunta.
Para crear una instancia de una clase interna, primero debe crear una instancia de la clase externa. Luego, crea el objeto interno dentro del objeto externo con esta sintaxis:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
ver: Tutorial de Java - Clases anidadas
Para completar, tenga en cuenta que también existe una clase interna sin una instancia adjunta :
class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}
Aquí, la new A() { ... }
es una clase interna definida en un contexto estático y no tiene una instancia adjunta.
Terminología: las clases anidadas se dividen en dos categorías: estáticas y no estáticas. Las clases anidadas que se declaran estáticas se denominan simplemente clases anidadas estáticas. Las clases anidadas no estáticas se denominan clases internas.
En el lenguaje común, los términos "anidado" e "interno" se usan de manera intercambiable por la mayoría de los programadores, pero usaré el término correcto "clase anidada" que cubre tanto la interna como la estática.
Las clases se pueden anidar hasta el infinito , por ejemplo, la clase A puede contener la clase B, que contiene la clase C, que contiene la clase D, etc. Sin embargo, más de un nivel de anidación de clases es raro, ya que generalmente es un mal diseño.
Hay tres razones por las que puedes crear una clase anidada:
- organización: a veces parece más sensato ordenar una clase en el espacio de nombres de otra clase, especialmente cuando no se utilizará en ningún otro contexto
- acceso: las clases anidadas tienen acceso especial a las variables / campos de sus clases contenidas (precisamente qué variables / campos dependen del tipo de clase anidada, ya sea interna o estática).
- conveniencia: tener que crear un nuevo archivo para cada nuevo tipo es molesto, nuevamente, especialmente cuando el tipo solo se usará en un contexto
Hay cuatro tipos de clases anidadas en Java . En resumen, son:
- clase estática : declarado como miembro estático de otra clase
- clase interna : declarado como miembro de instancia de otra clase
- clase interna local : declarada dentro de un método de instancia de otra clase
- clase interna anónima : como una clase interna local, pero escrita como una expresión que devuelve un objeto único
Déjame elaborar en más detalles.
Clases estáticas
Las clases estáticas son las más fáciles de entender porque no tienen nada que ver con las instancias de la clase contenedora.
Una clase estática es una clase declarada como miembro estático de otra clase. Al igual que otros miembros estáticos, una clase de este tipo es en realidad una percha que utiliza la clase contenedora como su espacio de nombres, por ejemplo , la clase Cabra declarada como miembro estático de la clase Rhino en el paquete pizza se conoce con el nombre de pizza.Rhino.Goat .
package pizza;
public class Rhino {
...
public static class Goat {
...
}
}
Francamente, las clases estáticas son una característica bastante inútil porque las clases ya están divididas en espacios de nombres por paquetes. La única razón realmente posible para crear una clase estática es que dicha clase tiene acceso a los miembros estáticos privados de su clase contenedora, pero me parece que esta es una justificación bastante poco convincente para que exista la característica de clase estática.
Clases internas
Una clase interna es una clase declarada como miembro no estático de otra clase:
package pizza;
public class Rhino {
public class Goat {
...
}
private void jerry() {
Goat g = new Goat();
}
}
Al igual que con una clase estática, la clase interna se conoce como calificada por su nombre de clase contenedora, pizza.Rhino.Goat , pero dentro de la clase contenedora, puede conocerse por su nombre simple. Sin embargo, cada instancia de una clase interna está vinculada a una instancia particular de su clase contenedora: arriba, la Cabra creada en jerry , está ligada implícitamente a la instancia de Rhino en Jerry . De lo contrario, hacemos explícita la instancia de Rhino asociada cuando creamos una instancia de Goat :
Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();
(Tenga en cuenta que se refiere al tipo interno simplemente como Cabra en la extraña nueva sintaxis: Java deduce el tipo que contiene desde la parte del rinoceronte . Y, sí, el nuevo rinoceronte.Gorra () también tendría más sentido para mí).
Entonces, ¿qué nos gana esto? Bueno, la instancia de clase interna tiene acceso a los miembros de instancia de la instancia de clase contenedora. Se hace referencia a estos miembros de instancia adjuntos dentro de la clase interna a través de sus nombres simples, no a través de esto ( esto en la clase interna se refiere a la instancia de clase interna, no a la instancia de clase contenedora asociada):
public class Rhino {
private String barry;
public class Goat {
public void colin() {
System.out.println(barry);
}
}
}
En la clase interna, puede referirse a esto de la clase contenedora como Rhino.this , y puede usar esto para referirse a sus miembros, por ejemplo , Rhino.this.barry .
Clases internas locales
Una clase interna local es una clase declarada en el cuerpo de un método. Tal clase solo se conoce dentro de su método de contención, por lo que solo se puede crear una instancia y se puede acceder a sus miembros dentro de su método de contención. La ganancia es que una instancia de clase interna local está vinculada y puede acceder a las variables locales finales de su método de contención. Cuando la instancia utiliza un final local de su método de contención, la variable conserva el valor que tenía en el momento de la creación de la instancia, incluso si la variable ha salido del alcance (esto es efectivamente la versión cruda y limitada de los cierres de Java).
Debido a que una clase interna local no es miembro de una clase o paquete, no se declara con un nivel de acceso. (Sea claro, sin embargo, que sus propios miembros tienen niveles de acceso como en una clase normal).
Si se declara una clase interna local en un método de instancia, una instanciación de la clase interna está vinculada a la instancia contenida por el método que contiene esto en el momento de la creación de la instancia, por lo que los miembros de la instancia de la clase que contiene son accesibles como en una instancia clase interna Una clase interna local se crea una instancia simplemente a través de su nombre, por ejemplo , la clase interna local Cat se crea una instancia como nueva Cat () , no es la nueva. Cat () como se podría esperar.
Clases internas anónimas
Una clase interna anónima es una forma sintácticamente conveniente de escribir una clase interna local. Más comúnmente, una clase interna local se crea una instancia de la mayoría solo una vez cada vez que se ejecuta su método de contención. Sería bueno, entonces, si pudiéramos combinar la definición de clase interna local y su única instanciación en una forma de sintaxis conveniente, y también sería bueno si no tuviéramos que inventar un nombre para la clase (menos inútil) nombres que contiene tu código, mejor). Una clase interna anónima permite estas dos cosas:
new *ParentClassName*(*constructorArgs*) {*members*}
Esta es una expresión que devuelve una nueva instancia de una clase sin nombre que extiende ParentClassName . No puedes suministrar tu propio constructor; más bien, uno se suministra de forma implícita, lo que simplemente llama al súper constructor, por lo que los argumentos proporcionados deben ajustarse al súper constructor. (Si el padre contiene múltiples constructores, se llama al "más simple", "más simple" según lo determinado por un conjunto bastante complejo de reglas que no vale la pena molestarse en aprender en detalle, solo preste atención a lo que NetBeans o Eclipse le dicen).
Alternativamente, puede especificar una interfaz para implementar:
new *InterfaceName*() {*members*}
Dicha declaración crea una nueva instancia de una clase sin nombre que extiende Objeto e implementa InterfaceName . Nuevamente, no puedes suministrar tu propio constructor; en este caso, Java proporciona implícitamente un constructor no-arg, do-nothing (por lo que nunca habrá argumentos de constructor en este caso).
Aunque no puede dar un constructor a una clase interna anónima, aún puede hacer cualquier configuración que desee utilizando un bloque de inicialización (un bloque {} colocado fuera de cualquier método).
Tenga en cuenta que una clase interna anónima es simplemente una forma menos flexible de crear una clase interna local con una instancia. Si desea una clase interna local que implemente múltiples interfaces o que implemente interfaces mientras extiende alguna clase que no sea Object o que especifique su propio constructor, se quedará atascado creando una clase interna local denominada regular.
En el caso de crear una instancia, la instancia de la clase interna no estática se crea con la referencia del objeto de la clase externa en la que se define. Esto significa que ha inclinado la instancia. Pero la instancia de la clase interna estática se crea con la referencia de la clase externa, no con la referencia del objeto de la clase externa. Esto significa que no ha incluido ninguna instancia.
Por ejemplo:
class A
{
class B
{
// static int x; not allowed here…..
}
static class C
{
static int x; // allowed here
}
}
class Test
{
public static void main(String… str)
{
A o=new A();
A.B obj1 =o.new B();//need of inclosing instance
A.C obj2 =new A.C();
// not need of reference of object of outer class….
}
}
En términos simples, necesitamos clases anidadas principalmente porque Java no proporciona cierres.
Las clases anidadas son clases definidas dentro del cuerpo de otra clase adjunta. Son de dos tipos: estáticos y no estáticos.
Se tratan como miembros de la clase adjunta, por lo que puede especificar cualquiera de los cuatro especificadores de acceso: private, package, protected, public
. No tenemos este lujo con clases de nivel superior, que solo pueden ser declaradas public
o privadas de paquete.
Las clases internas también denominadas clases no apiladas tienen acceso a otros miembros de la clase superior, incluso si se declaran privadas, mientras que las clases anidadas estáticas no tienen acceso a otros miembros de la clase superior.
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1
es nuestra clase interna estática e Inner2
es nuestra clase interna que no es estática. La diferencia clave entre ellos es que no se puede crear una instancia de Inner2
sin un Outer externo, ya que puede crear un objeto Inner1
independiente.
¿Cuándo usarías la clase interna?
Piense en una situación en la que la Class A
y la Class B
están relacionadas, la Class B
necesita acceder a Class A
miembros de la Class A
y la Class B
está relacionada solo con la Class A
Las clases internas entran en escena.
Para crear una instancia de clase interna, necesita crear una instancia de su clase externa.
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
o
OuterClass.Inner2 inner = new OuterClass().new Inner2();
¿Cuándo usarías la clase interna estática?
Definiría una clase interna estática cuando sepa que no tiene ninguna relación con la instancia de la clase adjunta / clase superior. Si su clase interna no usa métodos o campos de la clase externa, es solo un desperdicio de espacio, así que hágalo estático.
Por ejemplo, para crear un objeto para la clase anidada estática, use esta sintaxis:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
La ventaja de una clase anidada estática es que no necesita un objeto de la clase que contiene / clase superior para funcionar. Esto puede ayudarlo a reducir la cantidad de objetos que su aplicación crea en el tiempo de ejecución.
Existe una sutileza sobre el uso de clases estáticas anidadas que pueden ser útiles en ciertas situaciones.
Mientras que los atributos estáticos se instancian antes de que la clase se ejemplifique a través de su constructor, los atributos estáticos dentro de las clases estáticas anidadas no parecen ser instanciados hasta después de que el constructor de la clase sea invocado, o al menos no hasta después de que los atributos sean referenciados por primera vez, incluso si están marcados como ''finales''.
Considera este ejemplo:
public class C0 {
static C0 instance = null;
// Uncomment the following line and a null pointer exception will be
// generated before anything gets printed.
//public static final String outerItem = instance.makeString(98.6);
public C0() {
instance = this;
}
public String makeString(int i) {
return ((new Integer(i)).toString());
}
public String makeString(double d) {
return ((new Double(d)).toString());
}
public static final class nested {
public static final String innerItem = instance.makeString(42);
}
static public void main(String[] argv) {
System.out.println("start");
// Comment out this line and a null pointer exception will be
// generated after "start" prints and before the following
// try/catch block even gets entered.
new C0();
try {
System.out.println("retrieve item: " + nested.innerItem);
}
catch (Exception e) {
System.out.println("failed to retrieve item: " + e.toString());
}
System.out.println("finish");
}
}
A pesar de que ''anidado'' y ''innerItem'' están declarados como ''final estático''. la configuración de nested.innerItem no se lleva a cabo hasta que se crea una instancia de la clase (o al menos no hasta que se hace referencia por primera vez al elemento estático anidado), como puede ver por sí mismo al comentar y desmentir las líneas a las que me refiero, encima. Lo mismo no es válido para ''outerItem''.
Al menos esto es lo que estoy viendo en Java 6.0.
La instancia de la clase interna se crea cuando se crea la instancia de la clase externa. Por lo tanto, los miembros y los métodos de la clase interna tienen acceso a los miembros y los métodos de la instancia (objeto) de la clase externa. Cuando la instancia de la clase externa queda fuera del alcance, también las instancias de la clase interna dejan de existir.
La clase anidada estática no tiene una instancia concreta. Simplemente se carga cuando se usa por primera vez (al igual que los métodos estáticos). Es una entidad completamente independiente, cuyos métodos y variables no tienen acceso a las instancias de la clase externa.
Las clases anidadas estáticas no se juntan con el objeto externo, son más rápidas y no toman memoria de pila / pila, porque no es necesario crear una instancia de dicha clase. Por lo tanto, la regla de oro es tratar de definir la clase anidada estática, con el alcance más limitado posible (privado> = clase> = protegido> = pública), y luego convertirla a clase interna (eliminando el identificador "estático") y aflojar El alcance, si es realmente necesario.
Los términos se usan indistintamente. Si desea ser realmente pedante al respecto, entonces podría definir "clase anidada" para referirse a una clase interna estática, una que no tiene una instancia adjunta. En el código, podría tener algo como esto:
public class Outer {
public class Inner {}
public static class Nested {}
}
Sin embargo, esa no es realmente una definición ampliamente aceptada.
No creo que haya mucho que agregar aquí, la mayoría de las respuestas explican perfectamente las diferencias entre la clase anidada estática y las clases internas. Sin embargo, tenga en cuenta el siguiente problema al usar clases anidadas frente a clases internas. Como se menciona en un par de respuestas, no se puede crear una instancia de las clases internas sin una instancia de su clase envolvente, lo que significa que sostienen un puntero a la instancia de su clase envolvente, lo que puede provocar un desbordamiento de memoria o una excepción de desbordamiento de pila debido al hecho de que el GC no podrá recolectar las clases adjuntas aunque no se usen más. Para que quede claro, revisa el siguiente código:
public class Outer {
public class Inner {
}
public Inner inner(){
return new Inner();
}
@Override
protected void finalize() throws Throwable {
// as you know finalize is called by the garbage collector due to destroying an object instance
System.out.println("I am destroyed !");
}
}
public static void main(String arg[]) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
// out instance is no more used and should be garbage collected !!!
// However this will not happen as inner instance is still alive i.e used, not null !
// and outer will be kept in memory until inner is destroyed
outer = null;
//
// inner = null;
//kick out garbage collector
System.gc();
}
Si eliminas el comentario en // inner = null;
El programa pondrá " ¡Estoy destruido! ", Pero manteniendo este comentario no lo hará.
La razón es que todavía se hace referencia a la instancia interna blanca. GC no puede recopilarla y porque hace referencia (tiene un puntero a) a la instancia externa que no se recopila también. Tener suficiente de estos objetos en su proyecto y puede quedarse sin memoria.
Comparado con las clases internas estáticas que no tienen un punto en la instancia de la clase interna porque no está relacionado con la instancia sino con la clase. El programa anterior puede imprimir " ¡Estoy destruido! " Si hace que la clase Interna sea estática e instanciada con Outer.Inner i = new Outer.Inner();
No creo que la verdadera diferencia se aclarara en las respuestas anteriores.
Primero para obtener los términos correctos:
- Una clase anidada es una clase que está contenida en otra clase en el nivel del código fuente.
- Es estático si lo declara con el modificador estático .
- Una clase anidada no estática se llama clase interna. (Me quedo con la clase anidada no estática.)
La respuesta de Martin es correcta hasta ahora. Sin embargo, la pregunta real es: ¿cuál es el propósito de declarar estática o no una clase anidada?
Utiliza clases anidadas estáticas si solo desea mantener sus clases juntas si pertenecen tópicamente juntas o si la clase anidada se usa exclusivamente en la clase adjunta. No hay diferencia semántica entre una clase anidada estática y cualquier otra clase.
Las clases anidadas no estáticas son una bestia diferente. Similar a las clases internas anónimas, tales clases anidadas son en realidad cierres. Eso significa que capturan su alcance circundante y su ejemplo adjunto y lo hacen accesible. Quizás un ejemplo lo aclare. Ver este talón de un Contenedor:
public class Container {
public class Item{
Object data;
public Container getContainer(){
return Container.this;
}
public Item(Object data) {
super();
this.data = data;
}
}
public static Item create(Object data){
// does not compile since no instance of Container is available
return new Item(data);
}
public Item createSubItem(Object data){
// compiles, since ''this'' Container is available
return new Item(data);
}
}
En este caso, desea tener una referencia de un elemento secundario al contenedor principal. Usando una clase anidada no estática, esto funciona sin algún trabajo. Puede acceder a la instancia adjunta de Container con la sintaxis Container.this
.
Más explicaciones de hardcore siguientes:
Si observa los códigos de byte de Java que genera el compilador para una clase anidada (no estática), podría ser aún más claro:
// class version 49.0 (49)
// access flags 33
public class Container$Item {
// compiled from: Container.java
// access flags 1
public INNERCLASS Container$Item Container Item
// access flags 0
Object data
// access flags 4112
final Container this$0
// access flags 1
public getContainer() : Container
L0
LINENUMBER 7 L0
ALOAD 0: this
GETFIELD Container$Item.this$0 : Container
ARETURN
L1
LOCALVARIABLE this Container$Item L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 1
public <init>(Container,Object) : void
L0
LINENUMBER 12 L0
ALOAD 0: this
ALOAD 1
PUTFIELD Container$Item.this$0 : Container
L1
LINENUMBER 10 L1
ALOAD 0: this
INVOKESPECIAL Object.<init>() : void
L2
LINENUMBER 11 L2
ALOAD 0: this
ALOAD 2: data
PUTFIELD Container$Item.data : Object
RETURN
L3
LOCALVARIABLE this Container$Item L0 L3 0
LOCALVARIABLE data Object L0 L3 2
MAXSTACK = 2
MAXLOCALS = 3
}
Como puede ver, el compilador crea un Container this$0
campo oculto de Container this$0
. Esto se establece en el constructor que tiene un parámetro adicional de tipo Container para especificar la instancia adjunta. No puede ver este parámetro en la fuente, pero el compilador lo genera implícitamente para una clase anidada.
El ejemplo de martin
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
sería compilado para una llamada de algo como (en bytecodes)
new InnerClass(outerObject)
En aras de la exhaustividad:
Una clase anónima es un ejemplo perfecto de una clase anidada no estática que simplemente no tiene un nombre asociado y no se puede hacer referencia más adelante.
Destinatarios, que son principiantes en Java y / o clases anidadas
Las clases anidadas pueden ser:
1. Clases anidadas estáticas.
2. Clases anidadas no estáticas. (también conocido como clases internas ) => Por favor recuerda esto
1. clases internas
Ejemplo:
class OuterClass {
/* some code here...*/
class InnerClass { }
/* some code here...*/
}
Las clases internas son subconjuntos de clases anidadas:
- clase interna es un tipo específico de clase anidada
- Las clases internas son subconjuntos de clases anidadas.
- Puede decir que una clase interna también es una clase anidada, pero NO puede decir que una clase anidada también es una clase interna .
Especialidad de clase interna:
- La instancia de una clase interna tiene acceso a todos los miembros de la clase externa, incluso a aquellos que están marcados como "privados"
2. Clases anidadas estáticas:
Ejemplo:
class EnclosingClass {
static class Nested {
void someMethod() { System.out.println("hello SO"); }
}
}
Caso 1: Creación de una instancia de una clase anidada estática de una clase no contenedora
class NonEnclosingClass {
public static void main(String[] args) {
/*instantiate the Nested class that is a static
member of the EnclosingClass class:
*/
EnclosingClass.Nested n = new EnclosingClass.Nested();
n.someMethod(); //prints out "hello"
}
}
Caso 2: Creación de una instancia de una clase anidada estática desde una clase adjunta
class EnclosingClass {
static class Nested {
void anotherMethod() { System.out.println("hi again"); }
}
public static void main(String[] args) {
//access enclosed class:
Nested n = new Nested();
n.anotherMethod(); //prints out "hi again"
}
}
Especialidad de clases estáticas:
- La clase interna estática solo tendría acceso a los miembros estáticos de la clase externa y no tendría acceso a los miembros no estáticos.
Conclusión:
Pregunta: ¿Cuál es la principal diferencia entre una clase interna y una clase anidada estática en Java?
Respuesta: simplemente revise los detalles de cada clase mencionada anteriormente.
La clase interna y la clase estática anidada en Java son clases declaradas dentro de otra clase, conocida como clase de nivel superior en Java. En la terminología de Java, si declara una clase anidada estática, se llamará clase estática anidada en Java, mientras que las clases anidadas no estáticas se denominan simplemente Clase Interna.
¿Qué es la Clase Interna en Java?
Cualquier clase que no sea un nivel superior o declarada dentro de otra clase se conoce como clase anidada y fuera de esas clases anidadas, la clase que se declara no estática se conoce como clase interna en Java. Hay tres tipos de clases internas en Java:
1) Clase interna local: se declara dentro de un bloque de código o método.
2) Clase interna anónima: es una clase que no tiene nombre para referenciar y se inicializa en el mismo lugar donde se crea.
3) Clase interna de miembro: se declara como miembro no estático de la clase externa.
public class InnerClassTest {
public static void main(String args[]) {
//creating local inner class inside method i.e. main()
class Local {
public void name() {
System.out.println("Example of Local class in Java");
}
}
//creating instance of local inner class
Local local = new Local();
local.name(); //calling method from local inner class
//Creating anonymous inner class in Java for implementing thread
Thread anonymous = new Thread(){
@Override
public void run(){
System.out.println("Anonymous class example in java");
}
};
anonymous.start();
//example of creating instance of inner class
InnerClassTest test = new InnerClassTest();
InnerClassTest.Inner inner = test.new Inner();
inner.name(); //calling method of inner class
}
//Creating Inner class in Java
private class Inner{
public void name(){
System.out.println("Inner class example in java");
}
}
}
¿Qué es la clase estática anidada en Java?
La clase estática anidada es otra clase que se declara dentro de una clase como miembro y se hace estática. La clase estática anidada también se declara como miembro de la clase externa y se puede hacer privada, pública o protegida como cualquier otro miembro. Uno de los principales beneficios de la clase estática anidada sobre la clase interna es que la instancia de la clase estática anidada no se adjunta a ninguna instancia de la clase externa. Tampoco necesita ninguna instancia de Clase externa para crear una instancia de clase estática anidada en Java .
1) Puede acceder a miembros de datos estáticos de la clase externa, incluidos los privados.
2) La clase anidada estática no puede acceder al miembro o método de datos no estáticos (instancia) .
public class NestedStaticExample {
public static void main(String args[]){
StaticNested nested = new StaticNested();
nested.name();
}
//static nested class in java
private static class StaticNested{
public void name(){
System.out.println("static nested class example in java");
}
}
}
Ref: Clase interna y clase estática anidada en Java con ejemplo
Creo que la gente aquí debería notar a Poster que: Clase de nido estático solo la primera clase interna. Por ejemplo:
public static class A {} //ERROR
public class A {
public class B {
public static class C {} //ERROR
}
}
public class A {
public static class B {} //COMPILE !!!
}
Entonces, resumir, la clase estática no depende de qué clase contiene. Por lo tanto, no pueden en la clase normal. (porque la clase normal necesita una instancia).
He ilustrado varios posibles escenarios correctos y de error que pueden ocurrir en el código Java.
class Outter1 {
String OutStr;
Outter1(String str) {
OutStr = str;
}
public void NonStaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// below static attribute not permitted
// static String tempStatic1 = "static";
// below static with final attribute not permitted
// static final String tempStatic1 = "ashish";
// synchronized keyword is not permitted below
class localInnerNonStatic1 {
synchronized public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
public static void StaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// static attribute not permitted below
//static String tempStatic1 = "static";
// static with final attribute not permitted below
// static final String tempStatic1 = "ashish";
class localInnerNonStatic1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
// synchronized keyword is not permitted
static class inner1 {
static String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
public static void innerStaticMethod(String str11) {
// error in below step
str11 = temp1 +" india";
//str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
//}
}
//synchronized keyword is not permitted below
class innerNonStatic1 {
//This is important we have to keep final with static modifier in non
// static innerclass below
static final String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
synchronized public void innerMethod(String str11) {
tempNonStatic = tempNonStatic +" ...";
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// error in below step
public static void innerStaticMethod(String str11) {
// error in below step
// str11 = tempNonStatic +" india";
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
//}
}
}
La diferencia es que una declaración de clase anidada que también es estática puede ser instanciada fuera de la clase envolvente.
Cuando tienes una declaración de clase anidada que no es estática, también conocida como clase interna , Java no te permitirá crear instancias, excepto a través de la clase adjunta. El objeto creado fuera de la clase interna está vinculado al objeto creado desde la clase externa, por lo que la clase interna puede hacer referencia a los campos de la clase externa.
Pero si es estático, entonces el enlace no existe, no se puede acceder a los campos externos (excepto a través de una referencia común como cualquier otro objeto) y, por lo tanto, puede instanciar la clase anidada por sí misma.
Ummm ... una clase interna ES una clase anidada ... ¿te refieres a clase anónima y clase interna?
Edición: si realmente quisiste decir interno vs anónimo ... una clase interna es solo una clase definida dentro de una clase como:
public class A {
public class B {
}
}
Mientras que una clase anónima es una extensión de una clase definida de forma anónima, no se define ninguna clase real, como en:
public class A {
}
A anon = new A() { /* you could change behavior of A here */ };
Edición adicional:
Wikipedia afirma que hay una diferencia en Java, pero he estado trabajando con Java durante 8 años, y es la primera vez que escucho tal distinción ... sin mencionar que no hay referencias para respaldar la afirmación ... línea, una clase interna es una clase definida dentro de una clase (estática o no), y anidada es solo otro término que significa lo mismo.
Hay una diferencia sutil entre la clase anidada estática y no estática ... básicamente, las clases internas no estáticas tienen acceso implícito a los campos y métodos de instancia de la clase adjunta (por lo tanto, no pueden construirse en un contexto estático, será un compilador error). Las clases anidadas estáticas, por otro lado, no tienen acceso implícito a los campos y métodos de la instancia, y PUEDEN construirse en un contexto estático.
Clase anidada es un término muy general: toda clase que no sea de nivel superior es una clase anidada. Una clase interna es una clase anidada no estática. Joseph Darcy escribió una muy buena explicación acerca de las clases de nivel superior, interna, interna y miembro .
Cuando declaramos una clase miembro estática dentro de una clase, se conoce como clase anidada de nivel superior o una clase anidada estática. Se puede demostrar de la siguiente manera:
class Test{
private static int x = 1;
static class A{
private static int y = 2;
public static int getZ(){
return B.z+x;
}
}
static class B{
private static int z = 3;
public static int getY(){
return A.y;
}
}
}
class TestDemo{
public static void main(String[] args){
Test t = new Test();
System.out.println(Test.A.getZ());
System.out.println(Test.B.getY());
}
}
Cuando declaramos una clase miembro no estática dentro de una clase, se conoce como clase interna. La clase interna se puede demostrar de la siguiente manera:
class Test{
private int i = 10;
class A{
private int i =20;
void display(){
int i = 30;
System.out.println(i);
System.out.println(this.i);
System.out.println(Test.this.i);
}
}
}
El siguiente es un ejemplo de static nested class
y inner class
:
OuterClass.java
public class OuterClass {
private String someVariable = "Non Static";
private static String anotherStaticVariable = "Static";
OuterClass(){
}
//Nested classes are static
static class StaticNestedClass{
private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable";
//can access private variables declared in the outer class
public static void getPrivateVariableofOuterClass(){
System.out.println(anotherStaticVariable);
}
}
//non static
class InnerClass{
//can access private variables of outer class
public String getPrivateNonStaticVariableOfOuterClass(){
return someVariable;
}
}
public static void accessStaticClass(){
//can access any variable declared inside the Static Nested Class
//even if it private
String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable;
System.out.println(var);
}
}
Prueba externa de clase:
public class OuterClassTest {
public static void main(String[] args) {
//access the Static Nested Class
OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();
//test the private variable declared inside the static nested class
OuterClass.accessStaticClass();
/*
* Inner Class Test
* */
//Declaration
//first instantiate the outer class
OuterClass outerClass = new OuterClass();
//then instantiate the inner class
OuterClass.InnerClass innerClassExample = outerClass. new InnerClass();
//test the non static private variable
System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass());
}
}
En primer lugar, no existe una clase llamada Clase estática. El uso del modificador estático con la clase interna (llamada Clase anidada) dice que es un miembro estático de Clase externa, lo que significa que podemos acceder a él como con otros miembros estáticos y sin tener instancia de clase externa. (Que es beneficio de la estática originalmente.)
La diferencia entre usar una clase anidada y una clase interna regular es:
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
Primero podemos crear una instancia de Outerclass y luego podemos acceder a Inner.
Pero si la clase está anidada, la sintaxis es:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
Que utiliza la sintaxis estática como implementación normal de palabra clave estática.