Para comprender el principio de reflexión, primero debe comprender qué tipo de información es. Java nos permite identificar la información de objetos y clases en tiempo de ejecución, y hay dos formas principales: una es la RTTI tradicional, que supone que ya conocemos toda la información de tipo en el momento de la compilación; El otro es el mecanismo de reflexión, que nos permite descubrir y usar la información de las clases en tiempo de ejecución .
1. Objeto de clase
Para comprender cómo funciona RTTI en Java, primero debe saber cómo se representa la información de tipo en tiempo de ejecución. Esto se hace por objetos de clase, que contiene información relacionada con las clases. Los objetos de clase se utilizan para crear todos los objetos "regulares". Java usa objetos de clase para realizar RTTI, incluso si realiza operaciones como la conversión de tipo.
Cada clase generará un objeto de clase correspondiente, que se guarda en un archivo .class. Todas las clases se cargan dinámicamente al JVM cuando se usan por primera vez. Esta clase se cargará cuando el programa cree una referencia a un miembro estático de la clase. Los objetos de clase se cargan solo cuando es necesario, y la inicialización estática se realiza cuando se carga la clase.
clase pública TestMain {public static void main (String [] args) {System.out.println (xyz.name);}} clase xyz {public static string name = "luoxn28"; static {system.out.println ("xyz bloque estático");}} public xyz () {System.out.println ("xyz static block"); construido ");}}El resultado de la salida es:
El cargador de clase primero verifica si el objeto de clase de esta clase se ha cargado. Si no se ha cargado, el cargador de clase predeterminado buscará el archivo .class correspondiente basado en el nombre de la clase.
Para usar información de tipo en tiempo de ejecución, debe obtener una referencia al objeto de clase del objeto (como un objeto base). Puede usar la función class.forname ("base") para lograr esto, o usar base.class. Tenga en cuenta que es interesante. Al usar la función ".class" para crear una referencia a un objeto de clase, el objeto de clase no se inicializará automáticamente, y el uso de FORNAME () inicializará automáticamente el objeto de clase. Los preparativos para usar clases generalmente tienen los siguientes 3 pasos:
• Carga: completada por el cargador de clases, busque el bytecode correspondiente y cree un objeto de clase
• Enlace: verifique el bytecode en la clase y asigne espacio para el dominio estático
• Inicialización: si la clase tiene una superclase, se inicializa y se ejecutan el inicializador estático y el bloque de inicialización estática.
Public Class Base {static int num = 1; static {System.out.println ("base" + num);}} public class Main {public static void main (string [] args) {// Los bloques estáticos no se inicializarán class clazz1 = base.class; system.out.println ("-------"); // class clazz2 = Class.forname ("zzz.base");}} 2. Verifique antes de la conversión de tipo
El compilador verificará si el tipo de transición hacia abajo es legal y si no es legal, se lanzará una excepción. Antes de convertir el tipo hacia abajo, puede usar instancia para juzgar.
class Base { }class Derived extends Base { }public class Main {public static void main(String[] args) {Base base = new Derived();if (base instanceof Derived) {// Here you can down-convert System.out.println("ok");}else {System.out.println("not ok");}}} 3. Reflexión: información de tiempo de ejecución
Si no conoce el tipo exacto de un objeto, RTTI puede decirle, pero hay un requisito previo: este tipo debe ser conocido en el momento de la compilación para que RTTI pueda usarse para identificarlo. La clase de clase admite la reflexión junto con la biblioteca de clase Java.lang.Reflect. Esta biblioteca de clase contiene clases de campo, método y constructor. Los objetos de estas clases son creados por el JVM en el inicio para representar a los miembros correspondientes en clases desconocidas. De esta manera, puede usar el Contructor para crear un nuevo objeto, usar los métodos get () y establecer () para obtener y modificar los campos asociados con el objeto de campo en la clase y usar el método Invoke () para llamar al método asociado con el objeto del método. Además, también se puede llamar a muchos métodos convenientes como getfields (), getMethods () y getConstructors () para devolver una matriz que representa campos, métodos y objetos constructores. De esta manera, la información del objeto puede determinarse completamente en tiempo de ejecución sin saber nada sobre la clase en el momento de la compilación.
No hay nada mágico en el mecanismo de reflexión. Al tratar con un objeto de tipo desconocido a través de la reflexión, el JVM simplemente verifica el objeto para ver a qué clase específica pertenece. Por lo tanto, la clase. La clase de esa clase debe ser notable para el JVM, ya sea en la máquina local o desde la red. Entonces, la diferencia real entre RTTI y la reflexión es solo:
• RTTI, el compilador abre y verifica los archivos de clasificación en el momento de la compilación
• Reflexionar, abrir y verificar los archivos .class en tiempo de ejecución
La persona de clase pública implementa serializable {private String name; private int age; // get/set método} public static void main (string [] args) {persona persona = nueva persona ("Luoxn28", 23); class clazz = persona.getClass (); campo [] fields = clazz.getDeclaredfields (); para (campo de campo: fields) {string key field.getName (); PropertyDescriptor Descriptor = New PropertyDescriptor (Key, Clazz); Method Method = Descriptor.GetReadMethod (); Object Value = Method.invoke (Person); System.out.println (Key + ":" + Value);}}}}} La llamada anterior La función Get de la clase a través del método getReadMethod (), y el método getWriteMethod () se puede usar para llamar al método establecido de la clase. En términos generales, no necesitamos usar herramientas de reflexión, pero son más útiles para crear un código dinámico. La reflexión se usa en Java para admitir otras características, como la serialización de objetos y los javabeans.
4. Agente dinámico
El modo proxy es proporcionar operaciones adicionales o diferentes, y los objetos insertados se utilizan para reemplazar objetos "reales", que implican comunicación con objetos "reales", por lo que el proxy generalmente actúa como intermediario. El proxy dinámico de Java está un paso por delante de la idea de proxy, que puede crear dinámicamente y proxie y manejar llamadas a los métodos proxy dinámicamente. Todas las llamadas realizadas en el proxy dinámico se redirigen a un solo procesador de llamadas, y su trabajo es revelar el tipo de llamada y determinar la política correspondiente. Aquí hay un ejemplo de un proxy dinámico:
Clases de interfaz e implementación:
Interfaz de interfaz pública {void dosomthing (); void somethingeLse (string arg);} public class RealObject Interface {public void dosomthingthetting () {System.out.println ("dosomthing.");} public void tomething (string arg) {system.println ("something" + arg);}}}}}}}}}}}}}} Procesador de objeto proxy dinámico:
La clase pública DynamicProxyHandler implementa InvocationHandler {private Object proxyed; public DynamicProxyHandler (objeto proxyed) {this.proxyed = proxyed;}@overridePublic Object Invoke (Object Proxy, método, método, objeto [] argumenta ilegalaccessexception, ilegalargument, invocategetExceptException {system.out (argumenta) El proxy está funcionando. "); return Method.Invoke (proxyed, args);}} Clase de prueba:
public class Main {public static void main (string [] args) {realObject real = new RealObject (); interface proxy = (interface) proxy.newproxyinstance (interface.class.getclassloader (), nueva clase [] {interface.class}, nueva DynamicProxyHandler (real)); proxy.dosomethething (); proxy.somethingelse ("Luoxn28");}}El resultado de salida es el siguiente:
Puede crear un proxy dinámico llamando al método estático proxy proxy.newproxyInstance (). Este método requiere un cargador de clase, una lista de interfaces que desea que implementen el proxy (no una clase o clase abstracta) y una clase de implementación de InvocationHandler. El proxy dinámico puede redirigir todas las llamadas al procesador de llamadas, por lo que el constructor del procesador de llamadas generalmente pasa una referencia al objeto "real", que reenviará la solicitud cuando el procesador de llamadas realice la tarea de mediación.
Lo anterior es la comprensión profunda de la reflexión de Java introducida por el editor para usted. Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje y el editor le responderá a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!