Field class
The Field class defines some methods that can be used to query the type of a field and to set or read the value of a field. Combining these methods with the inherited member method allows us to find out all information about the field declaration and be able to manipulate fields of a specific object or class.
The getGenericType method returns a Type instance representing the declaration type of the field. For trivial types like String or int, the method returns Class objects associated with it, such as String.class and int.classo For parameterized types like List <Stri ng>, the method returns an instance of Parameterizedrype, for example, for types like T, the method returns a Typevariable instance.
The legacy getType method will return a Class object of type of the field. For trivial types, the method behaves the same as the getGenericType method. If the declared type of the field is a parameterized type, the getType method will return the corresponding Class object for the erase of the parameterized type, that is, the Class object of the original type. For example, for an object declared as List <Stri ng>, getType will return Li St. class. If the declared type of a field is a type variable, the getType method will return the corresponding class object for erasing the type variable. For example, suppose there is a class FOO<Ding>, and for fields declared as T type, getDing ype will return object.
class object. If FOO is declared as FOO<extends Number>, then ype under get will return Number.class.
We can use the isEnumConstant method to query whether a field is an enum constant, or we can use the get and set methods to get and set the value of the field. These methods that accept object citations and return the Object ect value have a common form, as well as some more specialized forms that can directly deal with basic types. All these methods accept a quotation to specify the object to be operated on. For static fields, this object quotation will be ignored, so you can also set it
Set to null. The following method will print the value of the short field of an object:
public static void printShortField(Object o, String name) throws NoSuchFieldException, IllegalAccessException { Field field=o.getClass().getField(name); short value=(Short) field.get(o); System.out.println(value);The return value of the get method can be any object referenced by this field. If the field is a primitive type, the method will return the appropriate type of wrapper class object. For our "hort-type field, the get method returns an object of type short containing the value of the field, and when assigned to the local variable value, the object value will be automatically unboxed.
The use of the set method is similar. The method of setting the short field to the provided value may look like this:
public static voi setShortField(Object o, String name, short nv) throws NoSuchFieldException, IllegalAccessException Field field=0.getClass().getField(name); field .set(o .nv);
Although set accepts parameters of Object type, we can directly pass a short value and wrap it into a short object with wrapping conversion.
In the above method, if the domain of the specified object is inaccessible and this access control is enforced, an IllegalACcessException exception will be thrown; if the object passed is different from the type of the domain, an illegalArgumentException exception will be thrown; if the domain is non-static and the object reference passed is null, a NullPointerException exception will be thrown; accessing a static domain may require the class to be initialized, so the method will also throw an ExceptionInInitializerError exception.
The Field class also has specific methods for getting and setting basic types. For example, we can call getPrimitive7ype and set Primitive7ype on the Field object, where Primitive7ype is the (capitalized) basic type name. The get method can be used in the following statement:
short value=field.getshhort(o);
The set method can be used in the following statement:
field.setshort(o, nv);
The use of wrapper-type objects can be avoided in statements declared in the above two ways.
The Field class implements the AnnotatedElement interface, so we can also query and apply it to the domain like Section 16.2.
Notes on.
With the method described above, we can use the Field object as a way to manipulate any value, but we should try to avoid it. Because the Java language catches programming errors as many as possible during the compilation period of a program, the fewer indirect methods such as "ield objects" are used when we write code, the more errors can be prevented before compiling them into code. Moreover, we can see that in the previous code, in order to know what exactly will happen, we have obviously spent a lot more energy on reading code than when using domain names directly in ordinary syntax.
Final fields
Normally setting a field declared final will cause an IllegalACcessException to be thrown
Exception, this is what we can expect, because the value of the final field will never change. But there are some special cases - for example, in customized deserialization (see Section 20.8.4), it makes sense to change the value of the final field, which we can only achieve through reflection on the instance field, and only if setAccessible(true) has been called on the Field object. Note that it is not enough to successfully call setAccessible(true) and it must be called indeed.
This capability is provided for highly specialized contexts and is not for general purpose, and we introduce it to maintain the integrity of the content only. If you are out of a specific context, such as customized deserialization, changing the value of the final field can lead to unexpected or even catastrophic consequences. Outside these contexts, there is no guarantee that changes to the final field are visible. Even in such contexts, it is necessary to ensure that the security mechanism does not hinder the execution of the code when encoding using this technology. Changing the final field with a value of constant variable (see Section 2.2.3) will make this change invisible unless such modification is achieved by using reflection.
Method class
The method class and its inherited methods from the member class allow us to obtain the complete information about the method declaration:
" public Type getGenericReturnTypeO: This method returns a Type object of the return type of the target method. If the target method is declared to return void, the method returns void.classo
" public Type[] getGenericParameterTypes(): This method returns an array of Type objects of all parameter types of the target method, which will be stored in the array in the order of declaration of the parameters. If the target method does not have any parameters, the method returns an empty array.
.publ ic Type [] getGeneri cacheti onTypes Q: This method returns an array of Type objects of all exception types listed in the throws clause, which will be stored in the array in the order of exception declaration.
If the target method does not declare any exceptions, the method returns an empty array.
Java also provides getReturnType, getParameterTypes and getExceptionTypes methods to return Cl as" object instead of Type object. Just like when using Field.getType, parameterized type and type variables are represented by the Class object corresponding to their erase.
The method class implements AnnotatedElement, and we can query the annotations applied to the method as discussed in Section 16.2. In addition, the Method class also provides getParameterAnnotations to provide access to annotations applied to method parameters. The getParameterAnnotations method can return an Annotation array, where each element of the outermost array corresponds to the method's parameters; if a parameter does not have any annotations, the method returns an Annotation array of length 0 for this parameter. If the method represented by the method object is itself an annotation element, then the getDefaultvalue method will return an Object object representing the default value of the element; if the method object itself is not an annotation element or it does not have a default value, then the method will return null.Method class also implements GenericDeclaration, so the getTypeParameters method is defined, which will return an array of Typevariable objects. If the given method object represents not a generic method, the method returns an empty array.
We can use the isvarArgs method to check whether a method object is a variable index method, and the i sBridge method can be used to check whether it is a bridge method
The most interesting way to use a Method object is to call itself reflectively:
.public object invoke(object onThis, object…args)throws IllegalACcessException, IllegalArgumentException, argetException under nvocation: This method calls the method defined by the method object onThis object, and uses the value of args to set the parameters of the called method. For non-static methods, the actual type of onThis determines which implementation of the method to be called, while for static methods, onThis will be ignored and is usually set to null. The number of values of args must be the same as the actual number of parameters of the called method, and the types of these values must be all assigned to the parameters of the called method; otherwise, we will get the llegalArgumentException exception. Note that the last parameter of the variable citation method is an array, so we have to fill the array with the "mutable" citations we actually want to pass. If we want to call a method that we do not have access, the method will throw an IllegalACcessException exception. If the called method is not the method of the on object, the method will throw a llegalArgumentExcepti on exception. If onThis is null and is non-static, the method will throw a NO 1PointerException exception. If this method object represents a static method and the class that declares the static method is still in the state to be initialized, the method will throw an ExceptionIn worker nitializerError exception. If the called method has an alien power, the InvocationTargetException exception will be thrown.
When we use the invoke method, we can directly pass the basic type, or we can use a suitable wrapper class. The type represented by the wrapper class must be assigned to the parameter type declared by the method. We can use Long, Float or Double to wrap double-type citations, but we cannot use Double to wrap long or float-type citations, because double can not be assigned to long or oat. The processing method of the object returned by the invoke method is the same as Field.get, which returns the basic type of the wrapper class corresponding to them. If the method is declared void, the invoke method will return null,
Simply put, when we use invoke to call methods, we can only use legal parameters in Java language.
Prioritizers with the same type and value. For example, the following call
return str.indexof(".", 8);It can be written in the following form using reflection:
Throwable fas; try{ Method indexM=String.class. getMethod("index0f",String.class, int.class); return (Integer) indexM.invoke(str,",",8); }catch (NoSuchMethodException e){ failure=e; }catch (InvocationTargetException e){ fas=e .getCause(); }catch (IllegalAccessException e){ failure=e; } throw fas;Although the compiler's security checks for direct calls can only be performed when using invoke at runtime when using reflection, reflection-based code does have semantically equivalent security checks to the direct-called code. Access checks may be performed in a slightly different way - the Security Manager may deny access to a method in our package, even if we can call it directly.
When we can use this form of call, we have good reason to avoid it. But it would make sense if we use the invoke or get/set method when writing a debugger or other generic application that needs to interpret user input as operation on objects. The method object can be used to some extent as a method pointer similar to that in other languages, but we have better tools, especially interfaces, abstract classes, and nested classes, which can be used to deal with problems that are usually solved with method pointers in other languages.