Cuando comencé a aprender Java, era realmente difícil entender qué era la reflexión.
Algunos libros, incluso los más clásicos, explican las cosas de una manera que confunde a la gente. Quizás soy demasiado estúpido.
Además, se dice en línea que el mecanismo de reflexión debe usarse con frecuencia al aprender marcos en el futuro, lo que siempre hace que la gente se sienta un poco incómoda.
Accidentalmente vi algunos capítulos y videos que explican la reflexión y creo que puedo entenderlo un poco mejor.
Ahora decidí trabajar duro, leer y escribir al mismo tiempo y registrar algunos contenidos y operaciones principales aquí.
Creo que para una persona estúpida como yo, quizás la mejor manera de aprender sea repitiendo.
Cuando encuentro algo que no entiendo, me detengo y lo aprendo de nuevo. Aunque me hace perder mucho tiempo, también tiene algún efecto en mí.
Según tengo entendido, la llamada reflexión consiste en restaurar la información completa de la clase en función de un objeto ya instanciado.
Al menos para mí, creo que el beneficio que me aporta es que me permite entender la orientación a objetos de abajo hacia arriba.
x_x Aquí odio esos cabezones otra vez, mataron todas mis células cerebrales.
clase claseSi desea completar la reflexión, debe comprender la clase Clase.
Ejemplo 1: obtener el nombre del paquete y el nombre de la clase a través del objetoprueba de clase {
}
Demostración de clase pública {
público estático vacío principal (String [] argumentos) {
Prueba t = nueva prueba();
System.out.println(t.getClass());
System.out.println(t.getClass().getName());
}
}
Los resultados de la compilación son los siguientes, solo preste atención a cómo se compila el paquete.
El método getClass() aquí se hereda de la clase Object de forma predeterminada.
En Java, la clase Objeto es la clase padre de todas las clases. De manera similar, los objetos instanciados de todas las clases también son instancias de la clase Clase.
Por lo tanto, esto involucrará los conceptos de transformación ascendente y transformación descendente.
Los genéricos también seguirán aquí debido a la inseguridad de las conversiones descendentes.
(¡Pero lo que quiero decir es que el diseño genérico aquí es muy deslumbrante! ¡Maldita sea, el diseño de sintaxis de todo Java también es deslumbrante, súper repugnante!)
Ejemplo 2: creación de instancias de la clase ClassDado que la clase Class no tiene constructor, la forma de crear una instancia de la clase Class es un poco especial. Hay tres formas:
Objeto.getClass()}
Demostración de clase pública {
público estático vacío principal (String [] argumentos) {
//Método 1:
Prueba t = nueva prueba();
Clase<? extiende Prueba> c1 = t.getClass();
System.out.println(c1);
//Método 2:
// Para evitar especificidades, aquí no se utiliza la clase Test, pero se utiliza la clase String en la biblioteca Java.
Clase<Cadena> c2 = Cadena.clase;
System.out.println(c2);
//Método 3:
//el método forName() generará una excepción
Clase<?> c3 = nulo;
intentar {
c3 = Class.forName("Prueba");
} captura (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c3);
}
}
Hay un método en la clase Class llamado newInstance (), que se puede usar para crear una nueva instancia del objeto de clase Class.
¿Cómo decirlo? El contenido contenido en el objeto Clase es la clase reflejada. Necesitamos construir una nueva instancia (nuevo objeto) de esa clase.
Ejemplo 3: construcción de un objeto sin parámetros de la clase Class //Generamos una referencia a una cadena
Cadena s = nula;
intentar {
//Transmitir el objeto construido a la clase String
//el método newInstance() arrojará una excepción
s = (Cadena) c.newInstance();
} captura (InstantiationException e) {
e.printStackTrace();
} captura (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Longitud de la cadena: " + s.length());
}
}
Esto construye un nuevo objeto en forma sin parámetros, como en el modo normal.
Construir un nuevo objeto a través del constructor sin argumentos es lo mismo que
Sabemos que además de los constructores sin parámetros, también hay constructores parametrizados en una clase.
Entonces, ¿cómo construir objetos en forma de parámetros en reflexión? Sigue leyendo
Ejemplo 4: objeto construido parametrizado de clase Class Demostración de clase pública {
// Los siguientes métodos arrojan demasiadas excepciones. Por razones de compacidad del código, aquí se lanzan directamente a la máquina virtual.
public static void main (String [] args) lanza una excepción {
Clase<?> c = nulo;
intentar {
c = Class.forName("java.lang.String");
} captura (ClassNotFoundException e) {
e.printStackTrace();
}
char[] ch = {'h','e','l','l','o'};
Cadena s = nula;
//Obtiene el constructor parametrizado del objeto Clase. Los parámetros entre paréntesis se escriben como: tipo.clase.
Constructor<?> con = c.getConstructor(char[].class);
//Utiliza este método de construcción para construir un nuevo objeto de cadena, el parámetro es una matriz de caracteres
s = (Cadena) con.newInstance(ch);
System.out.println("Cadena construida: " + s);
}
}
Seguimos usando la clase String como ejemplo, porque la clase String se usa con más frecuencia y es más fácil de entender.
Lo que hay que tener en cuenta aquí es que el constructor debe obtenerse mediante el método getConstructor()
En cuanto al tipo de parámetro, es: tipo original.clase
Otro punto es que, ya sea que tenga parámetros o no, el método de construcción utilizado aquí debe existir en la clase original.
Entonces, ¿cómo podemos conocer información detallada como el método constructor, el método ordinario, la clase principal heredada, etc. en la clase original? Sigue leyendo
Obtener la estructura de la clase.Para obtener la estructura de una clase a través de la reflexión, necesitamos importar un nuevo paquete java.lang.reflect
Ejemplo 5: Obtener el constructor de una clase Demostración de clase pública {
// Los siguientes métodos arrojan demasiadas excepciones. Por razones de compacidad del código, aquí se lanzan directamente a la máquina virtual.
public static void main (String [] args) lanza una excepción {
Clase<?> c = nulo;
intentar {
c = Class.forName("java.lang.Boolean");
} captura (ClassNotFoundException e) {
e.printStackTrace();
}
//El método getConstructors() aquí devuelve una matriz de constructores
Constructor<?>[] cons = c.getConstructors();
// Puedes escribir el método de impresión tú mismo. Por conveniencia, uso Arrays.toString() para arreglármelas.
System.out.println(Arrays.toString(contras));
}
}
Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
Clase<?> c = nulo;
intentar {
c = Class.forName("java.lang.Boolean");
} captura (ClassNotFoundException e) {
e.printStackTrace();
}
Clase<?>[] en = c.getInterfaces();
System.out.println(Arrays.toString(en));
}
}
Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
Clase<?> c = nulo;
intentar {
c = Class.forName("java.lang.Boolean");
} captura (ClassNotFoundException e) {
e.printStackTrace();
}
Método[] m = c.getMethods();
// Está bien, esta vez seré misericordioso y escribiré una lista impresa.
for (int i = 0; i < m.longitud; i++) {
System.out.println(m[i]);
}
}
}
clase Persona {
nombre de cadena privada;
edad privada;
}
Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
Clase<?> c = nulo;
intentar {
c = Class.forName("Persona");
} captura (ClassNotFoundException e) {
e.printStackTrace();
}
Campo[] f = c.getDeclaredFields();
for (int i = 0; i < f.length; i++) {
System.out.println(f[i]);
}
}
}
El método getDeclaredFielsd() puede obtener todas las propiedades y getFields() solo puede obtener propiedades públicas.
Ejemplo 10: Obtener el valor del atributo en esta clase clase Persona {
nombre de cadena pública;
edad privada;
Persona pública (nombre de cadena, edad int) {
this.nombre = nombre;
this.age = edad;
}
}
Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
Persona p = nueva Persona("zhangsan",12);
Clase<?> c = p.getClass();
//Obtener el valor del atributo público
Campo f1 = c.getField("nombre");
//get(p) indica qué valor del objeto se va a obtener
Cadena cadena = (Cadena) f1.get(p);
System.out.println("Nombre: " + cadena);
//Obtener el valor del atributo privado
Campo f2 = c.getDeclaredField("edad");
//la edad es una propiedad privada, así que establece la verificación de seguridad en verdadero
f2.setAccessible(verdadero);
int edad = (int) f2.get(p);
System.out.println("Edad: " + edad);
}
}
Francamente, no he encontrado ningún conocimiento en Java que pueda cegar mis ojos de titanio.
Cada vez, tengo que escribir un montón de sintaxis tediosas para implementar un dispositivo, o tengo que llamar a la API desesperadamente y lanzar excepciones desesperadamente.
Hacer que el código que no es lo suficientemente compacto se vuelva engorroso
Si me gusta un idioma, sus propias características deben impresionarme antes de que pueda usarlo para hacer algo.
Obviamente, Java no me hace feliz. Quizás muchos programadores como yo nos veamos obligados a utilizar Java.
Sólo para apaciguar mi solitario corazón codificador, sigue leyendo a continuación.
Ejemplo de aplicación de reflexión 11: modificar atributos mediante reflexión clase Persona {
nombre de cadena privada;
Persona pública (nombre de cadena) {
this.nombre = nombre;
}
cadena pública toString() {
devolver "Nombre: " + este.nombre;
}
}
Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
Persona p = nueva Persona("王二狗");
System.out.println(p);
Clase<?> c = p.getClass();
//Definir las propiedades a modificar
Campo f = c.getDeclaredField("nombre");
f.setAccessible(verdadero);
//Modificar propiedades y pasar el objeto y valor a establecer
f.set(p, "Zhang Erdan");
System.out.println(p);
}
}
clase Persona {
impresión pública vacía (int i) {
System.out.println("Estoy escribiendo números: " + i);
}
vacío estático público decir (String str) {
System.out.println("Estoy diciendo: " + str);
}
}
Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
Persona p = nueva Persona();
Clase<?> c = p.getClass();
//El método getMethod() necesita pasar el nombre del método y el tipo de parámetro.
Método m1 = c.getMethod("print", int.class);
//invoke() significa llamar y necesita pasar objetos y parámetros
m1.invocar(p, 10);
Método m2 = c.getMethod("decir", String.class);
// El nulo aquí significa no llamado por el objeto, es decir, un método estático
m2.invoke(nulo, "tu hermana");
}
}
Aquí hay una demostración de un método parametrizado normal y un método estático.
Ahora que todos los parámetros están escritos, los que no tienen parámetros son aún más simples. Simplemente pase un objeto directamente.
Ejemplo 13: manipulación de matrices mediante reflexión Demostración de clase pública {
public static void main (String [] args) lanza una excepción {
int[] arreglo = {1,2,3,4,5};
Clase<?> c = arr.getClass().getComponentType();
System.out.println("Tipo de matriz: " + c.getName());
int len = Array.getLength(arr);
System.out.println("Longitud de la matriz: " + len);
System.out.print("Atravesar la matriz: ");
para (int i = 0; i < len; i++) {
System.out.print(Array.get(arr, i) + " ");
}
System.out.println();
//modificar matriz
System.out.println("El primer elemento antes de la modificación: " + Array.get(arr, 0));
matriz.set(arr, 0, 3);
System.out.println("El primer elemento modificado: " + Array.get(arr, 0));
}
}
Eso es todo por el momento. El libro que leí también incluye la aplicación de reflexión en modo fábrica.
No es más que reemplazarlo con el método forName(). No hay mucho que decir.
Soy un principiante en Java. Odio la sintaxis y el diseño repugnantes de Java.
Todo esto es para Android, para sentar las bases y adaptarse al trabajo futuro.