Clase de campo
La clase de campo define algunos métodos que se pueden utilizar para consultar el tipo de campo y establecer o leer el valor de un campo. La combinación de estos métodos con el método de miembro heredado nos permite encontrar toda la información sobre la declaración de campo y poder manipular campos de un objeto o clase específico.
El método getGenericType devuelve una instancia de tipo que representa el tipo de declaración del campo. Para tipos triviales como String o INT, el método devuelve el objeto de clase asociado con él, como String.Class e Int.Classo para tipos parametrizados como List <Stri Ng>, el método devuelve una instancia de ParameterizeRyPE, por ejemplo, para un tipo como t, el método devuelve una instancia mecanografiable.
El método Legacy GetType devolverá un objeto de clase de tipo del campo. Para los tipos triviales, el método se comporta igual que el método getGenericType. Si el tipo declarado del campo es un tipo parametrizado, el método GetType devolverá el objeto de clase correspondiente para el borrado del tipo parametrizado, es decir, el objeto de clase del tipo original. Por ejemplo, para un objeto declarado como lista <Stri ng>, GetType devolverá Li St. Class. Si el tipo declarado de un campo es una variable de tipo, el método GetType devolverá el objeto de clase correspondiente para borrar la variable de tipo. Por ejemplo, suponga que hay una clase Foo <ding>, y para los campos declarados como tipo t, Getding YPE devolverá el objeto.
objeto de clase. Si Foo se declara como foo <extiende número>, entonces YPE Under get devolverá number.class.
Podemos usar el método isenumconstant para consultar si un campo es una constante enum, o podemos usar los métodos Get and Set para obtener y establecer el valor del campo. Estos métodos que aceptan citas de objetos y devuelven el valor del objeto ECT tienen una forma común, así como algunas formas más especializadas que pueden manejar directamente los tipos básicos. Todos estos métodos aceptan una cotización para especificar el objeto que se operará. Para los campos estáticos, se ignorará esta cita de objeto, por lo que también puede configurarla
Establecido en nulo. El siguiente método imprimirá el valor del campo corto de un objeto:
public static void printshortfield (objeto o, nombre de cadena) arroja nosuchfieldException, ilegalAccessException {campo campo = o.getClass (). getField (nombre); valor corto = (corto) campo.get (o); System.out.println (valor);El valor de retorno del método GET puede ser cualquier objeto mencionado por este campo. Si el campo es un tipo primitivo, el método devolverá el tipo apropiado de objeto de clase de envoltorio. Para nuestro campo "tipo Hort-tipo, el método GET devuelve un objeto de tipo corto que contiene el valor del campo, y cuando se asigna al valor variable local, el valor del objeto se deshacerá automáticamente.
El uso del método establecido es similar. El método para establecer el campo corto en el valor proporcionado puede verse así:
public static voi setShortfield (objeto o, nombre de cadena, breve nv) lanza NosuchfieldException, ilegalaccessexception campo campo = 0.getClass (). getField (nombre); campo .set (o .nv);
Aunque SET acepta parámetros del tipo de objeto, podemos pasar directamente un valor corto y envolverlo en un objeto corto con conversión de envoltura.
En el método anterior, si el dominio del objeto especificado es inaccesible y este control de acceso se aplica, se lanzará una excepción ilegalAccessException; Si el objeto aprobado es diferente del tipo de dominio, se lanzará una excepción ilegalargumentException; Si el dominio no es estático y la referencia del objeto es nula, se lanzará una excepción de NullPointerException; Acceder a un dominio estático puede requerir que la clase se inicialice, por lo que el método también lanzará una excepción de excepcióninitializerError.
La clase de campo también tiene métodos específicos para obtener y establecer tipos básicos. Por ejemplo, podemos llamar a getPrimitive7ype y establecer primitive7ype en el objeto de campo, donde primitive7ype es el nombre de tipo básico (capitalizado). El método GET se puede usar en la siguiente declaración:
valor corto = field.getShhort (o);
El método establecido se puede usar en la siguiente declaración:
campo.setShort (o, nv);
El uso de objetos de tipo envoltorio se puede evitar en las declaraciones declaradas de las dos maneras anteriores.
La clase de campo implementa la interfaz AnnotatedElement, por lo que también podemos consultar y aplicarla al dominio como la Sección 16.2.
Notas sobre.
Con el método descrito anteriormente, podemos usar el objeto de campo como una forma de manipular cualquier valor, pero debemos tratar de evitarlo. Debido a que el lenguaje Java capta errores de programación tantos como sea posible durante el período de compilación de un programa, cuanto menos métodos indirectos, como "objetos de IELD", se usan cuando escribimos código, más errores se pueden prevenir antes de compilarlos en el código. Además, podemos ver que en el código anterior, para saber qué sucederá exactamente, obviamente hemos gastado mucha más energía en el código de lectura que al usar nombres de dominio directamente en la sintaxis ordinaria.
Campos finales
Normalmente establecer un campo declarado final hará que se arroje una concepción ilegal
Excepción, esto es lo que podemos esperar, porque el valor del campo final nunca cambiará. Pero hay algunos casos especiales, por ejemplo, en la deserialización personalizada (ver sección 20.8.4), tiene sentido cambiar el valor del campo final, que solo podemos lograr a través de la reflexión en el campo de la instancia, y solo si SetAccessible (verdadero) se ha llamado en el objeto de campo. Tenga en cuenta que no es suficiente llamar con éxito a SetAccessible (verdadero) y debe llamarse de hecho.
Esta capacidad se proporciona para contextos altamente especializados y no es para fines generales, y lo presentamos para mantener la integridad del contenido únicamente. Si está fuera de un contexto específico, como la deserialización personalizada, cambiar el valor del campo final puede conducir a consecuencias inesperadas o incluso catastróficas. Fuera de estos contextos, no hay garantía de que se vean los cambios en el campo final. Incluso en tales contextos, es necesario garantizar que el mecanismo de seguridad no obstaculice la ejecución del código al codificar con esta tecnología. Cambiar el campo final con un valor de variable constante (ver Sección 2.2.3) hará que este cambio sea invisible a menos que dicha modificación se logre utilizando la reflexión.
Clase de método
La clase de método y sus métodos heredados de la clase miembro nos permiten obtener la información completa sobre la declaración del método:
"Tipo público getGenericReturnTypeO: este método devuelve un objeto de tipo del tipo de retorno del método de destino. Si se declara que el método de destino return void, el método devuelve void.classo
"Tipo público [] getGenericParametertypes (): este método devuelve una matriz de objetos de tipo de todos los tipos de parámetros del método de destino, que se almacenará en la matriz en el orden de declaración de los parámetros. Si el método de destino no tiene ningún parámetros, el método devuelve una matriz vacía.
.Public IC Type [] GetGeneri Cacheti OnTypes Q: Este método devuelve una matriz de objetos de tipo de todos los tipos de excepción enumerados en la cláusula de lanzamiento, que se almacenará en la matriz en el orden de la declaración de excepción.
Si el método de destino no declara ninguna excepción, el método devuelve una matriz vacía.
Java también proporciona métodos GetReturnType, GetParametertypes y GetExceptionTypes para devolver CL como "objeto en lugar de tipo objeto. Al igual que cuando se usa Field.gettype, las variables de tipo parametrizado y tipo están representadas por el objeto de clase correspondiente a su ERASE.
La clase de método implementa anotarseLement, y podemos consultar las anotaciones aplicadas al método como se discute en la Sección 16.2. Además, la clase de método también proporciona GetParameterNotations para proporcionar acceso a las anotaciones aplicadas a los parámetros del método. El método GetParameterNotations puede devolver una matriz de anotación, donde cada elemento de la matriz más externa corresponde a los parámetros del método; Si un parámetro no tiene anotaciones, el método devuelve una matriz de anotación de longitud 0 para este parámetro. Si el método representado por el objeto del método es en sí mismo un elemento de anotación, entonces el método getDefaultValue devolverá un objeto de objeto que represente el valor predeterminado del elemento; Si el objeto del método en sí no es un elemento de anotación o no tiene un valor predeterminado, entonces el método devolverá la clase NULL.method también implementa la facturación genérica, por lo que se define el método getTypeParameters, que devolverá una serie de objetos mecanograzosas. Si el objeto del método dado representa un método genérico, el método devuelve una matriz vacía.
Podemos usar el método ISVARARGS para verificar si un objeto de método es un método de índice variable, y el método i sbridge se puede usar para verificar si es un método de puente
La forma más interesante de usar un objeto de método es llamarse reflexivamente:
.Public Object Invoke (Object on este, objeto ... args) arroja ilegalAccessException, ilegalargumentException, argetException bajo nvocation: este método llama al método definido por el objeto del método en este objeto, y usa el valor de args para establecer los parámetros del método llamado. Para los métodos no estáticos, el tipo real de ONTHIS determina qué implementación del método a llamar, mientras que para los métodos estáticos, se ignorará y generalmente se establece en NULL. El número de valores de Args debe ser el mismo que el número real de parámetros del método llamado, y los tipos de estos valores deben estar asignados a los parámetros del método llamado; De lo contrario, obtendremos la excepción de LlegalarGumentException. Tenga en cuenta que el último parámetro del método de cita variable es una matriz, por lo que tenemos que llenar la matriz con las citas "mutables" que realmente queremos pasar. Si queremos llamar a un método al que no tenemos acceso, el método lanzará una excepción ilegalAccessException. Si el método llamado no es el método del objeto ON, el método lanzará un LlegalarGumentExcepti en la excepción. Si ONTHIS es nulo y no es estatal, el método lanzará una excepción no 1PointerException. Si este objeto del método representa un método estático y la clase que declara el método estático aún está en el estado a inicializarse, el método lanzará una excepción en la excepción de NitializerError del trabajador. Si el método llamado tiene un poder alienígena, se lanzará la excepción de InvocetTargetException.
Cuando usamos el método de Invoke, podemos pasar directamente el tipo básico, o podemos usar una clase de envoltorio adecuada. El tipo representado por la clase de envoltorio debe asignarse al tipo de parámetro declarado por el método. Podemos usar citas largas, flotantes o dobles para envolver citas de doble tipo, pero no podemos usar el doble para envolver citas largas o de tipo flotante, porque el doble no se puede asignar a largo o avena. El método de procesamiento del objeto devuelto por el método de Invoke es el mismo que Field.get, que devuelve el tipo básico de la clase de envoltorio correspondiente a ellos. Si el método se declara nulo, el método de invoca devolverá nulo,
En pocas palabras, cuando usamos los métodos de Invoke to Call, solo podemos usar parámetros legales en el lenguaje Java.
Priorizadores con el mismo tipo y valor. Por ejemplo, la siguiente llamada
return str.indexof (".", 8);Se puede escribir en la siguiente forma utilizando la reflexión:
Fas tirable; Pruebe {método indexm = string.class. getMethod ("index0f", string.class, int.class); return (entero) indexm.invoke (str, ",", 8); } catch (nosuchmethodexception e) {falla = e; } catch (invocationTargetException e) {fas = e .getCause (); } catch (ilegalAccessException e) {falla = e; } tirar fas;Aunque las verificaciones de seguridad del compilador para llamadas directas solo se pueden realizar al usar Invoke en tiempo de ejecución cuando se usa Reflexión, el código basado en la reflexión tiene verificaciones de seguridad semánticamente equivalentes al código llamado directo. Las verificaciones de acceso se pueden realizar de una manera ligeramente diferente: el administrador de seguridad puede negar el acceso a un método en nuestro paquete, incluso si podemos llamarlo directamente.
Cuando podemos usar esta forma de llamada, tenemos buenas razones para evitarla. Pero tendría sentido si usamos el método Invoke o Get/Set al escribir un depurador u otra aplicación genérica que necesite interpretar la entrada del usuario como operación en objetos. El objeto del método se puede utilizar en cierta medida como un puntero de método similar al de otros idiomas, pero tenemos mejores herramientas, especialmente interfaces, clases abstractas y clases anidadas, que pueden usarse para lidiar con problemas que generalmente se resuelven con punteros de métodos en otros idiomas.