Además de proporcionarnos varias información sobre la obtención de clases durante el período de compilación, Java también nos permite obtener varias información sobre las clases durante el período de ejecución a través de la reflexión. Recuperar información de clase a través de la reflexión y después de obtener información de clase, puede obtener el siguiente contenido relacionado:
Este artículo también presentará la reflexión de Java desde los aspectos anteriores. Todos los códigos involucrados en este artículo se reflejan
Primero, se publica una clase Java como objeto de investigación para la reflexión. El contenido de la clase es el siguiente:
Public Abstract Class PheadObject implementa Runnable {public void dosomethingthething () {System.out.println ("hacer cosas ..."); }} clase pública EjemploObject extiende PadreObject {public int Age = 30; Nombre de cadena pública = "Byhieg"; Puntuación entera privada = 60; public void printName () {System.out.println (nombre); } public int getAge () {return Age; } public void setAge (int Age) {this.age = edad; } public String getName () {nombre de retorno; } public void setName (nombre de cadena) {this.name = name; } public integer getScore () {puntaje de retorno; } public void setScore (puntaje Integer) {this.score = stork; } public EJEMPLECHECEJET () {} public EjemploObject (nombre de cadena) {} public EjemploObject (int Age, Integer Score) {} @Override public void dosomething () {super.dosomting (); } @Override public void run () {system.out.println ("ejecutar ..."); }}Objeto de clase
Nuestra aplicación utilizará el punto de conocimiento de la reflexión. Debemos querer obtener la información de la clase en tiempo de ejecución y hacer algunas operaciones específicas basadas en la información de la clase. Luego, lo primero es obtener la información de la clase, y se proporciona un objeto de clase en el JDK para guardar la información de la clase. Por lo tanto, el primer paso en la reflexión es obtener el objeto de clase. Hay dos formas de obtener objetos de clase en JDK.
El primero es que si conoce el nombre de la clase al escribir código, puede obtener directamente el objeto de clase de la siguiente manera:
Class exampleObjectClass = ExampleObject.class;
El segundo tipo es que si no sabe el nombre de la clase al escribir el código, pero en tiempo de ejecución, puede obtener una cadena del nombre de la clase y puede obtener el objeto de clase de la siguiente manera:
Class exampleObjectClass = Class.forName("cn.byhieg.reflectiontutorial.ExampleObject");
Tenga en cuenta que este método debe tener 2 condiciones. Primero, la cadena en Forname debe ser completamente calificada, y en segundo lugar, la clase de clase debe estar debajo de la ruta del ClassPath, porque el método lanzará una excepción de ClassNotFoundException.
Después de obtener este objeto de clase, puede obtener varias información sobre la clase. Al principio se ha mencionado alguna información. A continuación, hablemos sobre la información sobre la clase que no se ha mencionado.
Obtenga el nombre de la clase
Hay dos formas de obtener el nombre de la clase, uno es GetName () y el otro es GetSimpLename (). El primero obtiene un nombre completamente calificado, y el segundo obtiene un nombre de esta clase sin un nombre de paquete. Mire el siguiente ejemplo: Class Object, que se ha obtenido a través del código anterior.
Cadena fullClassName = EjemploObjectClass.getName (); Cadena simplecLassName = ejemploObjectClass.getSimplename (); System.out.println (FullClassName); System.out.println (simpleclassname); System.out.println (simpleclassname);
Los resultados son los siguientes:
cn.byhieg.reflectiontutorial.exampleObjectExampleBject
Obtenga el nombre del paquete de la clase, la clase principal y la interfaz de implementación
El nombre del paquete y la clase principal de la clase se pueden obtener a través del siguiente código.
// Obtener información de paquete paquete apackage = ejemploObjectClass.getPackage (); System.out.println (apackage); // Obtener clase principal de clase superclass = ejemploObjectClass.getSuperClass (); System.out.println (superclass.getSimplename ());
Los resultados son los siguientes:
paquete cn.byhieg.reflectiontutorialfatherObject
Obviamente, obtener el valor de retorno de la clase principal también es un objeto de clase. Luego, puede usar este objeto para obtener información sobre la clase principal, como juzgar si la clase principal es una clase abstracta.
System.out.println("父类是不是抽象类" + Modifier.isAbstract(superClass.getModifiers()));
GetModifiers puede obtener modificadores de clase, por lo tanto, obtener modificadores de clase. Por supuesto, este getModificadores no solo puede llamarse objetos de clase, sino que se pueden llamar a los objetos de métodos.
Puede usar el método en la clase java.lang.reflect.modifier para verificar el tipo de modificador:
Modificador.isabstract (int modificadores); modificador.isfinal (int modificadores); modificador.isinterface (int modificadores); modificador.isnative (int modificadores); modificador.isprivate (int modificadores); modifier.Isprotected (int modifiers); modifier.IsPublic.IsPublic); modificadores de modificadores (INTIMSTATIC (INTIMSTATIC (INTIMSTATIC (INTUSTÁTICOS (INTENTÁTICOS (INTENTÁTICOS INTEN modificadores); modificador.isstrict (mod modificadores); modificador.issynchronized (int modificadores); modificador.istransient (int modificadores); modificador.isvolatile (int modificadores);
Además, también podemos obtener la interfaz implementada por la clase principal
// Obtener la clase de interfaz [] classes = superclass.getInterfaces (); System.out.println ("Interfaces of Chado de clase" + clases [0]);Debido a que las clases de Java pueden implementar muchas interfaces, usan matrices, pero cuando realmente las usan, primero debe determinar la longitud de la matriz.
A continuación, nos centraremos en explicar el contenido mencionado anteriormente.
Constructor
Usando la reflexión de Java, puede obtener un constructor de clase y crear dinámicamente un objeto en tiempo de ejecución basado en el constructor. Primero, Java obtiene una instancia del constructor por:
// constructorConstrucor [] constructores = ejemploObjectClass.getConstructors (); para (constructor constructor: constructores) {system.out.println (constructor.toString ()); }Los resultados son los siguientes:
público cn.byhieg.reflectiontutorial.exampleObject (int, java.lang.integer) público cn.byhieg.reflectiontutorial.exampleObject (java.lang.string) público cn.byhieg.reflectiontutorial.exampleObject ()
Si conoce el tipo de parámetro del constructor para acceder por adelantado, puede usar el siguiente método para obtener el constructor especificado, de la siguiente manera:
Constructor constructor = ejemploObjectClass.getConstructor (string.class); System.out.println (constructor.toString ());
El resultado es obviamente:
public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String)
Otro constructor también se puede obtener de la siguiente manera
Constructor constructor = ejemploObjectClass.getConstrucor (int.class, integer.class); System.out.println (constructor.toString ());
Además, si no conocemos los parámetros del constructor y solo podemos obtener todos los objetos del constructor, podemos obtener los parámetros que cada constructor usa de la siguiente manera:
Constructor [] constructores = ejemploObjectClass.getConstructors (); for (constructor constructor: constructors) {class [] parametertypes = constructor.getParametertyPes (); System.out.println ("Los parámetros del constructor son como sigue =================================================================== ========================================================================================================== para (clase clz: parametertypes) {system.out.println ("parametertype" + clz.toString ());Los resultados son los siguientes:
Los parámetros del constructor son los siguientes ==================================== Parámetro Tipo de parámetro Java.lang.String Los parámetros del constructor son los siguientes.
Aquí, se puede ver que el método de construcción sin parámetros no imprime el resultado. El objeto de clase del tipo básico y el objeto de clase del tipo de referencia son diferentes.
Ahora, se puede crear un objeto basado dinámicamente en varias información del constructor.
Objeto objeto = constructor.newinstance (1,100); System.out.println (object.ToString ());
Hay dos condiciones para crear un objeto. El primero se crea a través de un constructor de parámetros. El segundo es que el objeto del constructor debe obtenerse a través del getConstructor que pasa en la información de los parámetros.
La primera condición es que para los objetos que se pueden crear sin métodos de construcción de parámetros, no es necesario obtener el objeto constructor. El objeto de clase llama al método NewInStance () y crea el objeto directamente.
La segunda condición es que el objeto constructor debe obtenerse a través del formulario ejemploObjectClass.getConstructor (String.Class); Sería un error obtener la matriz de constructor a través de GetConstructors y luego llamar al objeto Constructor especificado para crear el objeto en JDK1.8. Pero JDK1.6 es normal.
variable
Usando la reflexión de Java, puede obtener información variable de una clase en tiempo de ejecución, y puede crear un objeto y establecer su valor variable de acuerdo con el método anterior. Primero, todas las variables públicas se obtienen siguiendo el siguiente método:
Campo [] campos = ejemploObjectClass.getFields (); for (campo campo: campos) {system.out.println ("variable es:" + field.toString ()); }Los resultados son los siguientes:
La variable es: public int cn.byhieg.reflectiontutorial.exampleObject.age La variable es: público java.lang.string cn.byhieg.reflectiontutorial.exampleBject.name
Obviamente, todas las variables públicas obtenidas son públicas, y no se obtiene la puntuación de variable privada anterior.
De la misma manera que se obtiene el constructor, podemos especificar un nombre de parámetro y luego obtener la variable especificada:
Campo campo = ejemploObjectClass.getField ("edad"); System.out.println ("variable es:" + field.toString ());El nombre obtenido por el método ToString de la variable anterior es demasiado largo. Java proporciona el método GetName a la clase de campo, que devuelve el nombre de la variable escrita en la clase. El código anterior se puede cambiar a Field.getName ().
La reflexión no solo proporciona una forma de obtener variables, sino que también proporciona una forma de establecer valores variables. Siguiendo el siguiente método, puede cambiar el valor variable de una clase generada dinámicamente:
EjemploObject Object = ((EjemploObject) constructor1.newinstance ("byhieg")); System.out.println ("La edad original es" + object.age); campo.set (objeto, 10); System.out.println ("La edad después del cambio es" + object.age);Los resultados son los siguientes:
La edad original es de 30 años y la edad después del cambio es 10
De acuerdo con el código anterior, puede obtener un objeto de campo llamado Age, luego llamar al método establecido del objeto, pasar un objeto y el valor que se cambiará, y luego puede cambiar el valor del objeto. Tenga en cuenta que este método no solo es útil para las variables miembros, sino también para las variables estáticas. Por supuesto, si es una variable estática, está bien pasar nulo sin pasar el objeto.
método
Además de proporcionarnos información variable de la clase, Java Reflection también nos proporciona información sobre el método. La reflexión nos permite obtener el nombre del método, los parámetros del método, el tipo de retorno del método y los métodos de llamadas.
Primero, obtenga el método a través del siguiente código:
// El método público del método de clase de salida [] métodos = ejemploObjectClass.getMethods (); para (método método: métodos) {system.out.println ("método ="+ método.getName ()); }Código que parece familiar como obtener variables. GetName se llama directamente aquí para que se escriba el nombre del método en la clase. Habiendo escrito esto, debe pensar naturalmente que Java también proporciona métodos específicos basados en parámetros.
Método método = ejemploObjectClass.getMethod ("setage", int.class); System.out.println (método.getName ());La diferencia aquí es que el método GetMethod también debe pasar en la información de tipo de parámetro, reflejando proporciona un método para obtener parámetros de método y tipo de retorno. Los ejemplos de parámetros de método de obtención son los siguientes:
Método método = ejemploObjectClass.getMethod ("setage", int.class); System.out.println (método.getName ()); for (clase clz: método.getParametertypes ()) {System.out.println ("Parámetro del método" + clz.getName ()); }Los resultados son los siguientes:
El parámetro int del método setAGE
Un ejemplo de obtención del tipo de retorno del método es el siguiente:
System.out.println(method.getReturnType().getName());
Los resultados son los siguientes:
void
Además, Java Reflection admite métodos obtenidos a través de llamadas de Invoke. Los ejemplos son los siguientes:
method.invoke(exampleObjectClass.newInstance(),1);
El primer parámetro Invoca es este objeto, y el segundo parámetro es una matriz de longitud variable, y los parámetros del método se pasan. Al igual que los objetos de campo, para métodos estáticos, puede pasar métodos nulos y estáticos.
Variables privadas y métodos privados
El método anterior solo puede obtener métodos y variables públicas, pero no puede obtener métodos y variables modificados no públicos. Java proporciona métodos adicionales para obtener variables y métodos no públicos. Es decir, las variables y métodos privados se obtienen a través de los métodos de GetDeclaredFields y GetDeclaredMethods. También admite el uso de GetDeclaredfield (nombre de variable) y getDeclaredMethod (nombre del método) para obtener el nombre de la variable especificada y el nombre del método. Sin embargo, los objetos de campo y los objetos de método obtenidos de esta manera no pueden usarse directamente. Estos objetos deben llamarse setAccessible (verdadero) para uso normal. El siguiente método puede ser el mismo que se mencionó anteriormente.
anotación
Primero escriba una clase que contenga anotaciones:
@Myannotation (name = "byhieg", value = "Hello World") Public Class AnnotationObject {@myannotation (name = "Field", valor = "variable") Campo de cadena pública; @Myannotation (name = "método", valor = "método") public void dosomthing () {System.out.println ("hacer algo"); } public void dootherthing (@myannotation (name = "param", value = "param") string param) {}}@retención (retenciónPolicy.runtime) public @Interface myAnnotation {public String name (); Valor de cadena pública ();}Java nos proporciona información sobre la obtención de anotaciones de clase en tiempo de ejecución, y podemos obtener anotaciones de clase, anotaciones de métodos, anotaciones de parámetros y anotaciones variables.
Al igual que el método de adquisición anterior, Java proporciona dos métodos de adquisición. Una es obtener todas las anotaciones y devolver una matriz, y la segunda es especificar las anotaciones especificadas.
Tomemos una anotación de clase como ejemplo para explicar las siguientes dos formas de obtener.
Clase clz = annotationObject.class; Anotación [] anotaciones = clz.getAnnotations (); Anotación anotación = clz.getAnnotation (annotationObject.class);
Luego, el procesamiento posterior se puede realizar en función de la anotación obtenida. El siguiente es un ejemplo de procesamiento:
para (anotación de anotación: anotaciones) {if (instancia de anotación de myAnnotation) {myAnnotation myAnnotation = (myAnnotation) anotación; System.out.println ("Nombre:" + myAnnotation.name ()); System.out.println ("Valor:" + myAnnotation.Value ()); }}Las anotaciones de clase anteriores se obtienen llamando a getNotations usando el objeto de clase. Las anotaciones del método y las anotaciones variables son las mismas. Llamo getDeclaredannotations utilizando objetos de método y objetos de campo respectivamente para obtener anotaciones. No tengo mucho que decir. Ver el código de reflexión por ejemplo
Las anotaciones de parámetros son un elemento relativamente problemático. Se compara el método de adquisición. El primer paso es obtener el objeto del método primero y llamar a GetParameterNotations. Sin embargo, este valor de retorno es una matriz bidimensional, porque el objeto del método tiene muchos parámetros, y cada parámetro puede tener muchas anotaciones. Los ejemplos son los siguientes:
Método método1 = clz.getMethod ("dootherthing", string.class); Anotación [] [] anotationInParam = Method1.getParameterAnnotations (); Clase [] params = método1.getParametertyPes (); int i = 0; para (anotación [] anotaciones: annotationInParam) {class para = params [i ++]; para (anotación de anotación: anotaciones) {if (instancia de anotación de myAnnotation) {myAnnotation myAnnotation = (myAnnotation) anotación; System.out.println ("param:" + para.getName ()); System.out.println ("Nombre:" + myAnnotation.name ()); System.out.println ("Valor:" + myAnnotation.Value ()); }}}Genéricos
Debido a que los genéricos Java se implementan a través de la borrado, es difícil obtener directamente información sobre el tipo de genéricos parametrizados específico, pero podemos obtener información genérica a través de una forma indirecta utilizando la reflexión. Por ejemplo, la siguiente clase:
public class GenericObject {public List <String> lists; Lista pública <String> getLists () {return lists; } public void setLists (list <string> lists) {this.lists = lists; }}Si un método devuelve una clase genérica, podemos llamar a getGenericReturnType a través del objeto del método para getGeniCreturnType para obtener cuál es el tipo de parametrización específico de esta clase genérica. Mira el siguiente código:
Clase clz = genericObject.class; Método método = clz.getMethod ("getLists"); Type genericType = método.getGenericReturnType (); if (instancia genericype de parameterizedType) {parameterizedType ParameterizedType = ((parameterizedType) genericType); Type [] tipos = parameterizedType.getActualTyPearGuments (); for (tipo tipo: tipos) {class realClz = ((class) type); System.out.println ("El tipo de parametrización es:" + realClz); }}Los resultados son los siguientes:
参数化类型为: class java.lang.String
Los pasos son un poco engorrosos, por lo que la siguiente explicación es:
Obtuve información específica sobre los genéricos mirando los resultados.
Si ningún método devuelve un tipo genérico, también podemos obtener el tipo parametrizado del tipo genérico por el parámetro del método como clase genérica, como el método de listas de set en la clase anterior. Los ejemplos son los siguientes:
Método setmethod = clz.getMethod ("setLists", list.class); Type [] GenericParametertypes = setmethod.getGenericParametertypes (); para (type GenericParamEtType: GenericParametertypes) {System.out.println ("GenericParametertypes es:" + GenericParametertype.gettypename ()); if (GenericParamTertype instancia de ParameterizedType) {ParameterizedType ParameterizedType = (((ParameterizedType) GenericParametertype); System.out.println ("ParameterizedType es:" + parameterizedType.gettypename ()); Types tipos [] = parameterizedType.getActualTyPearGuments (); para (tipo tipo: tipos) {system.out.println ("El tipo de parametrizado es:" + ((class) type) .getName ()); }}}Los resultados de la ejecución son los siguientes:
GenericParametertypes es: java.util.list <java.lang.string> parameterizedType es: java.util.list <java.lang.string> El tipo parametrizado es: java.lang.string
Debido a que los parámetros del método pueden tener más de un tipo genérico, GetGenericParametertypes para obtener una matriz, y debemos determinar si cada elemento tiene un tipo parametrizado. Los pasos posteriores son similares a los anteriores, por lo que no diré mucho.
Si incluso los parámetros del método no contienen clases genéricas, solo se deja el último caso, a través del tipo de variable, es decir, se utiliza la clase de campo. Los ejemplos son los siguientes:
Campo campo = clz.getfield ("listas"); Type type = field.getGenerictype (); if (tipo instancia de parameterizedType) {parameterizedType ParameterizedType = ((parameterizedType) type); Type [] tipos = parameterizedType.getActualTyPearGuments (); for (type type1: tipos) {system.out.println ("parameterized type:" + ((class) type1) .gettypeName ()); }}El principio es el mismo que el anterior, excepto que el objeto tipo es a través del campo.getGenerictype (), por lo que no diré mucho sobre las operaciones restantes.
Esta es la introducción para obtener el tipo parametrizado de genéricos a través de la reflexión.
Formación
La reflexión de Java puede operar en una matriz, incluida la creación de una matriz, acceder a valores en una matriz y obtener un objeto de clase de una matriz.
Hablemos de ello simplemente, crear una matriz y acceder a los valores en la matriz: usar la clase de matriz en reflexión es el debajo del paquete reflejar.
// Crear una matriz de tipo int con una longitud de 3 int [] intarray = (int []) array.newinstance (int.class, 3); // Asignar un valor a la matriz a través de la reflexión para (int i = 0; i <intarray.length; i ++) {array.set (intarray, i, i+2); } // matriz en forma de reflexión, obtenga el valor en la matriz para (int i = 0; i <intarray.length; i ++) {System.out.println (Array.get (Intarray, i)); }Lo anterior es crear una matriz y acceder a los valores en la matriz usando Reflection.
Para los objetos de clase que obtienen una matriz, simplemente puede usar int []. Class , o usar class.forname, que es una forma extraña de escribir:
Clase clz = class.forname ("[i"); System.out.println (clz.gettypename ());El resultado es:
int[]
La cadena en este forname, [ representa una matriz, represento una int, el flotador es f , el doble es d , etc. Si desea obtener una matriz de objetos ordinarios, use el siguiente formulario:
Class stringClz = Class.forName("[Ljava.lang.String;");
[ Digamos que es una matriz, el lado derecho de L es el nombre de clase, y el lado derecho del tipo es a ; ;
Esta forma de obtener el objeto de clase de la matriz es demasiado engorroso.
Después de obtener el objeto de clase de la matriz, se pueden llamar a algunos de sus métodos únicos, como llamar a GetComponentType para obtener la información de tipo de miembros de la matriz. Por ejemplo, una matriz int es un tipo de miembro, que es int.
System.out.println(clz.getComponentType().getTypeName());
El resultado es int
Resumir
Esta vez, las diversas aplicaciones de reflexión terminan con esto, y puede haber explicaciones de conocimiento en profundidad en el futuro. Para un código específico, puede mirar el código de reflexión
En el paquete SRC, hay varias clases, y en la clase de prueba, es acceso a estas clases.
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo sea de ayuda para el estudio o el trabajo de todos. ¡También espero apoyar a Wulin.com más!