inner - protected class java
¿Las clases internas se usan comúnmente en Java? ¿Son "malos"? (8)
¿Las clases internas se usan comúnmente en Java? ¿Son estas las mismas clases anidadas? ¿O han sido reemplazados en Java por algo mejor? Tengo un libro en la versión 5 y tiene un ejemplo que usa una clase interna, pero pensé que leía de alguna manera que las clases internas eran "malas".
No tengo ni idea y esperaba tener pensamientos al respecto.
Gracias.
Considere el siguiente ejemplo:
public class OuterClass {
private AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() {
@Override
protected void printAboutme() {
System.out.println("AnonymousInnerClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
};
public void displayAnonymousInnerClass() {
anonymousInnerClass.printAboutme();
}
public void displayStaticInnerClass() {
NestedStaticClass staticInnerClass = new NestedStaticClass();
staticInnerClass.printAboutMe();
}
public void displayInnerClass() {
InnerClass innerClass = new InnerClass();
innerClass.printAboutMe();
}
public void displayMethodInnerClass(){
class MethodInnerClass {
private String sampleField = "Method Inner Class";
public void printAboutMe() {
System.out.println("MethodInnerClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
}
MethodInnerClass methodInnerClass = new MethodInnerClass();
methodInnerClass.printAboutMe();
}
class InnerClass {
private String sampleField = "Inner Class";
public void printAboutMe() {
System.out.println("InnerClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
}
abstract class AnonymousInnerClass {
protected String sampleField = "Anonymous Inner Class";
protected abstract void printAboutme();
}
static class NestedStaticClass {
private String sampleField = "NestedStaticClass";
public void printAboutMe() {
System.out.println("NestedStaticClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
}
}
en este ejemplo, se comparan todos los tipos de clases anidadas no estáticas con clases anidadas estáticas. Ahora, si ejecuta el método de visualización de la clase Externa para cada clase anidada, verá la salida de cada método printAboutMe () de la clase anidada, que tiene algún código de reflexión. Para imprimir todas las variables miembro de las clases anidadas.
Verá que para las clases no anidadas hay una variable miembro adicional distinta de la cadena de variable declarada en el código, que solo está presente en el tiempo de ejecución.
por ejemplo, si ejecutamos el siguiente código para InnerClass. : -
public class NestedClassesDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.displayInnerClass();
}
}
La salida es así:
InnerClass.printAboutMe.........
private String sampleField
protected OuterClass this$0
Tenga en cuenta que hay una variable miembro misteriosa de $ 0 de tipo clase envolvente (clase externa).
Ahora está claro que las clases internas mantienen la referencia a la clase externa. Por lo tanto, el escenario de imagen en el que pasa la referencia de la clase interna a otra clase del mundo exterior y luego la referencia nunca se libera, a su vez también se hace referencia a OuterClass, por lo tanto, la fuga.
Por lo tanto, esto hace que el uso de clases internas sea malo si no se usa de forma inmediata.
No existe este caso con clases internas estáticas. Ejecute todos los métodos de visualización. Además, si hay algún problema en el código, señale.
La clave a recordar es que va a cambiar la flexibilidad por la simplicidad y la cohesión haciendo que las dos clases estén más unidas. Es posible que desee que las clases estén estrechamente vinculadas, pero está renunciando a la capacidad de intercambiar de forma transparente otras clases en lugar de lo que actualmente es su clase incorporada al no definir su clase desde una interfaz fuera de la clase contenedora.
Las clases internas no estáticas pueden ocultar un problema de rendimiento. Tienen acceso a los campos de miembros en la clase adjunta, pero no directamente, sino a través de captadores que se crean automáticamente. Esto será más lento y luego solo copiará los miembros de la clase adjunta a la clase interna.
Algunos otros problemas con las clases internas no estáticas se describen here
Las clases internas se usan con frecuencia, y algo muy similar, las clases anónimas, son prácticamente indispensables, ya que son lo más parecido que Java tiene a los cierres. Entonces, si no puedes recordar dónde escuchaste que las clases internas son malas, ¡trata de olvidarte de ello!
No creo que sean malos o malos. Tal vez no se usan mucho, pero tienen muchos usos, entre ellos los devoluciones de llamada. Una ventaja especial es que pueden extenderse desde una clase diferente a la clase externa, por lo que podría tener herencia múltiple.
Yo diría que uno de los problemas con las clases internas es que su sintaxis es algo "fea". Eso es algo que desalienta a algunas personas. Aquí en el trabajo hay muchos de ellos.
No son "malos" como tales.
Pueden estar sujetos a abusos (clases internas de clases internas, por ejemplo). Tan pronto como mi clase interna abarca más de unas pocas líneas, prefiero extraerla en su propia clase. Ayuda a la legibilidad y las pruebas en algunos casos.
Hay una cosa que no es inmediatamente obvia, y vale la pena recordarla. Cualquier clase interna no static
tendrá una referencia implícita a la clase externa circundante (una referencia implícita ''this''). Esto normalmente no es un problema, pero si llega a serializar la clase interna (por ejemplo, utilizando XStream ), encontrará que esto puede causarle un dolor inesperado.
Son útiles y pueden ser muy utilizados. Si bien debe tener cuidado al abusar de la funcionalidad, no son mucho más propensos a ser abusados que cualquier otra función de idioma.
Un buen ejemplo de una clase interna es la implementación del iterador para un tipo de colección dado. Es una clase que implementa una interfaz pública, pero no tiene ningún negocio existente excepto en asociación con otra clase. Te permite modelar cosas que en C ++ estarías obligado a hacer con el operador amigo.