Es posible que muchas personas no estén familiarizadas con las clases internas de Java. De hecho, existe un concepto similar en C ++, es decir, clases anidadas. Las diferencias y conexiones entre las dos se compararán a continuación. En la superficie, una clase interna es solo otra clase definida dentro de la clase (como verá a continuación, las clases internas se pueden definir en muchos lugares), pero en realidad no es tan simple a primera vista, las clases internas parecen un poco. redundante. La utilidad puede no ser tan obvia para los principiantes, pero con una comprensión más profunda, encontrará que los diseñadores de Java tienen buenas intenciones en las clases internas. Aprender a utilizar clases internas es parte del dominio de la programación Java avanzada, lo que le permite diseñar la estructura de su programa de manera más elegante. Presentémoslo desde los siguientes aspectos:
primera reunión
Copie el código de código de la siguiente manera:
Contenido de la interfaz pública {
valor int();
}
interfaz pública Destino {
Cadena readLabel();
}
Bienes de clase pública {
clase privada Contenido implementa Contenidos {
privado int i = 11;
valor int público() {
devolver yo;
}
}
La clase protegida GDestination implementa Destino {
etiqueta de cadena privada;
DestinoG privado(Cadena donde) {
etiqueta = donde;
}
cadena pública readLabel() {
etiqueta de devolución;
}
}
destino de destino público (cadena s) {
devolver nuevos destinos G;
}
Contenido público cont() {
devolver nuevo contenido();
}
}
clase TestGoods {
público estático vacío principal (String [] argumentos) {
Bienes p = nuevos Bienes();
Contenido c = p.cont();
Destino d = p.dest("Pekín");
}
}
En este ejemplo, las clases Contenido y DestinoG se definen dentro de la clase Bienes y tienen modificadores protegidos y privados respectivamente para controlar los niveles de acceso. El contenido representa el contenido de los Bienes y GDestination representa el destino de los Bienes. Implementan dos interfaces Contenido y Destino respectivamente. En el siguiente método principal, utiliza directamente Contenido c y Destino d para operar. ¡Ni siquiera ve los nombres de estas dos clases internas! De esta manera, el primer beneficio de las clases internas es ocultar operaciones que no desea que otros sepan, es decir, encapsulación.
Al mismo tiempo, también descubrimos la primera forma de sacar un objeto de clase interna fuera del alcance de la clase externa, que es crearlo y devolverlo usando los métodos de su clase externa. Los métodos cont() y dest() del ejemplo anterior hacen esto. Entonces, ¿hay alguna otra manera?
Por supuesto que sí,
el formato de sintaxis es el siguiente:
externalObject=new externalClass(Parámetros del constructor);
outsideClass.innerClass interiorObject=outerObject.new InnerClass(Parámetros del constructor);
Tenga en cuenta que al crear un objeto de clase interna no estática, primero debe crear el objeto de clase externa correspondiente. En cuanto al motivo, esto nos lleva a nuestro siguiente tema. Los objetos de clase interna no estática tienen referencias a sus objetos de clase externa.
Modifique ligeramente el ejemplo anterior:
Copie el código de código de la siguiente manera:
Bienes de clase pública {
tasa de valor int privada = 2;
clase privada Contenido implementa Contenidos {
privado int i = 11 * tasa de valor;
valor int público() {
devolver yo;
}
}
La clase protegida GDestination implementa Destino {
etiqueta de cadena privada;
DestinoG privado(Cadena donde) {
etiqueta = donde;
}
cadena pública readLabel() {
etiqueta de devolución;
}
}
destino de destino público (cadena s) {
devolver nuevos destinos G;
}
Contenido público cont() {
devolver nuevo contenido();
}
}
Aquí agregamos una variable miembro privada valueRate a la clase Goods, lo que significa que el coeficiente de valor de los bienes se multiplica por él cuando el método value() de la clase interna Content calcula el valor. Descubrimos que value() puede acceder a valueRate, que es el segundo beneficio de las clases internas. Un objeto de clase interna puede acceder al contenido del objeto de clase externa que lo creó, ¡incluso a variables privadas! Esta es una característica muy útil que nos proporciona más ideas y atajos a la hora de diseñar. Para lograr esta función, el objeto de clase interna debe tener una referencia al objeto de clase externa. Cuando el compilador de Java crea un objeto de clase interna, implícitamente pasa la referencia a su objeto de clase externa y la conserva. Esto permite que el objeto de clase interna siempre acceda a su objeto de clase externa, y esta es también la razón por la cual, para crear un objeto de clase interna fuera del alcance de la clase externa, primero debe crear su objeto de clase externa.
Algunas personas pueden preguntar, ¿qué debo hacer si una variable miembro de la clase interna tiene el mismo nombre que una variable miembro de la clase externa, es decir, la variable miembro de la clase externa con el mismo nombre está bloqueada? Está bien. Java usa el siguiente formato para expresar referencias a clases externas:
clase exterior.esto
Con ello no tememos esta situación de blindaje.
clase interna estática
Al igual que las clases ordinarias, las clases internas también pueden ser estáticas. Sin embargo, en comparación con las clases internas no estáticas, la diferencia es que las clases internas estáticas no tienen referencias externas. En realidad, esto es muy similar a las clases anidadas en C++. La mayor diferencia entre las clases internas de Java y las clases anidadas de C++ es si hay referencias al exterior. Por supuesto, desde una perspectiva de diseño y algunos de sus detalles, hay una diferencia.
Además, en cualquier clase interna no estática, no puede haber datos estáticos, métodos estáticos u otra clase interna estática (las clases internas pueden estar anidadas en más de un nivel). Pero puedes tener todo esto en clases internas estáticas. Esta puede considerarse como la segunda diferencia entre los dos.
clase interna local
Sí, las clases internas de Java también pueden ser locales, se pueden definir dentro de un método o incluso de un bloque de código.
Copie el código de código de la siguiente manera:
Bienes de clase pública1 {
destino de destino público (cadena s) {
clase GDestination implementa Destino {
etiqueta de cadena privada;
DestinoG privado(Cadena donde) {
etiqueta = donde;
}
cadena pública readLabel() {
etiqueta de devolución;
}
}
devolver nuevos destinos G;
}
público estático vacío principal (String [] argumentos) {
Bienes1 g = nuevos Bienes1();
Destino d = g.dest("Pekín");
}
}
Lo anterior es un ejemplo de ello. En el método dest, definimos una clase interna y finalmente este método devuelve el objeto de esta clase interna. Si solo necesitamos crear un objeto de una clase interna y crearlo en el exterior, podemos hacer esto. Por supuesto, las clases internas definidas en métodos pueden diversificar el diseño y sus usos no se limitan a esto.
Aquí hay un ejemplo aún más extraño:
Copie el código de código de la siguiente manera:
Bienes de clase pública2 {
Seguimiento interno vacío privado (booleano b) {
si (b) {
resbalón de seguimiento de clase {
identificación de cadena privada;
Hoja de seguimiento (cadena s) {
identificación = s;
}
cadena getDeslizamiento() {
identificación de devolución;
}
}
Trackingslip ts = new Trackingslip("deslizamiento");
Cadena s = ts.getslip();
}
}
pista pública vacía() {
seguimiento interno (verdadero);
}
público estático vacío principal (String [] argumentos) {
Bienes2 g = nuevos Bienes2();
g.pista();
}
}
No puedes crear un objeto de esta clase interna fuera del if, porque va más allá de su alcance. Sin embargo, durante la compilación, la clase interna Trackingslip se compila al mismo tiempo que otras clases, excepto que tiene su propio alcance y no es válida más allá de este alcance.
clase interna anónima
Las reglas de sintaxis de las clases internas anónimas de Java pueden parecer un poco extrañas, pero al igual que las matrices anónimas, cuando solo necesita crear un objeto de una clase y no necesita su nombre, el uso de clases internas puede hacer que el código parezca conciso y claro. Sus reglas de sintaxis son las siguientes:
nuevo nombre de interfaz(){......} o nuevo nombre de superclase(){......};
Sigamos con el siguiente ejemplo:
Copie el código de código de la siguiente manera:
Bienes de clase pública3 {
Contenido público cont() {
devolver nuevo contenido() {
privado int i = 11;
valor int público() {
devolver yo;
}
};
}
}
El método cont() aquí utiliza una clase interna anónima para devolver directamente un objeto de una clase que implementa la interfaz de Contenidos, lo que parece muy simple.
En los adaptadores anónimos para el procesamiento de eventos Java, las clases internas anónimas se utilizan ampliamente. Por ejemplo, cuando quieras cerrar la ventana, agrega este código:
Copie el código de código de la siguiente manera:
frame.addWindowListener(nuevo WindowAdapter(){
ventana vacía públicaClosing(WindowEvent e){
Sistema.salir(0);
}
});
Una cosa a tener en cuenta es que, dado que la clase interna anónima no tiene nombre, no tiene constructor (pero si la clase interna anónima hereda una clase principal que solo contiene un constructor parametrizado, debe traer estos parámetros al crearla y usar el super palabra clave para llamar al contenido correspondiente durante el proceso de implementación). Si desea inicializar sus variables miembro, existen varios métodos:
Si está en una clase interna anónima de un método, puede usar este método para pasar los parámetros que desee, pero recuerde, estos parámetros deben declararse finales.
Transforme la clase interna anónima en una clase interna local con nombre para que pueda tener un constructor.
Utilice un bloque de inicialización en esta clase interna anónima.
¿Por qué necesitas clases internas?
¿Cuáles son los beneficios de las clases internas de Java? ¿Por qué necesitas clases internas?
Primero, tomemos un ejemplo simple. Si desea implementar una interfaz, pero un método en esta interfaz tiene el mismo nombre y parámetros que un método en la clase que concibió, ¿qué debe hacer? En este momento, puede crear una clase interna para implementar esta interfaz. Dado que la clase interna es accesible para todo lo que está en la clase externa, al hacerlo se lograrán todas las funciones que tendría si implementara la interfaz directamente.
Pero quizás quieras preguntarte: ¿no sería suficiente simplemente cambiar el método?
De hecho, utilizar esto como motivo para diseñar clases internas no es realmente convincente.
La verdadera razón es esta: juntas, las clases e interfaces internas en Java pueden resolver un problema del que los programadores de C++ a menudo se quejan en Java sin herencia múltiple. De hecho, la herencia múltiple de C ++ es muy complicada de diseñar, y Java puede lograr muy bien el efecto de la herencia múltiple a través de clases e interfaces internas.