This is the 8th day of my participation in Gwen Challenge
Reflection mechanism
Reflection to create
Reflection, while the program is running, gets the properties and methods of the class
To be more specific, it can be divided into the following four points
- Gets the class to which the instance object belongs
- Gets member variables and methods in any class
- Calls the methods of the instance object
- Construct an instance object of the class
For a Java Class file, there are three ways to get a Class
- The getClass() method defined in the Object class, called through the instance Object
- Class name. Class, called directly
- Class.forname (), based on the path of the Class file
/* Instantiate the Object by calling the getClass() method defined in the Object class */
ArrayList<Integer> integers = new ArrayList<>();
System.out.println(integers.getClass().getName());
/* The second way is to get */ directly from the class name. Class
System.out.println(ArrayList.class.getName());
/* Get */ from the path where the class file is located
System.out.println(Class.forName("java.util.ArrayList"));
Copy the code
For the above three, it is recommended to use the class name. Class or class.forname ().
Note that only one Class file exists on the VM. The Class file obtained in the three methods is the same
In the Class Class, a number of methods are provided, some of which are briefly described, and the rest refer to the official API manual
String getName()
: Gets the fully qualified name of the class fileField[] getFields()
: Gets the public properties of the class fileField[] getDeclaredFields()
: Gets all the attributes of the class fileMethod[] getMethods()
: Public method to get a class fileMethod[] getDeclaredMethods()
: Gets all the methods of the class fileClass<? > forName(String className)
: Gets and loads the class file according to the qualified name
When you use an ArrayList container, you cannot determine the actual capacity of the instance objects of the container
At this point, you can use Java’s reflection mechanism to obtain the capacity properties within the instance object
public static void main(String[] args) throws NoSuchFieldException {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 150; i++) {
System.out.println("The first" + i + "Element before adding:"+ get(integers)); integers.add(i); }}public static Integer get(ArrayList
arrayList) {
try {
// Gets the specified property
Field elementData = arrayList.getClass().getDeclaredField("elementData");
// Set the property field to accessible
elementData.setAccessible(true);
// Actual value, return Object[]
Object[] o = (Object[]) elementData.get(arrayList);
return o.length;
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
return -1;
}
Copy the code
Below, we demonstrate the various parts of reflection using the ArrayList class
Field operations
Field[] getFields()
: Gets all public fields. Including the parent classField[] getDeclaredFields()
: Retrieves all fields, excluding the parent classField getField(String name)
: Gets the specified, public fieldField getDeclaredField(String name)
: gets the specified fieldString getName()
: Gets the name of the fieldboolean isAccessible(boolean flag)
: Indicates whether the user has the access permission for the fieldvoid setAccessible(boolean flag)
: Avoids the check and obtains the access permission for the fieldObject get(Object obj)
: gets the value of the specified field in the specified objectvoid set(Object obj, Object value)
: sets the value of the specified field in the specified object
ArrayList<Integer> integers = new ArrayList<>();
Field defaultCapacity = integers.getClass().getDeclaredField("DEFAULT_CAPACITY");
defaultCapacity.setAccessible(true);
Object o = defaultCapacity.get(integers);
System.out.println(o);
for (Field field : integers.getClass().getDeclaredFields()) {
field.setAccessible(true);
System.out.println(field);
}
/*
10
private static final long java.util.ArrayList.serialVersionUID
private static final int java.util.ArrayList.DEFAULT_CAPACITY
private static final java.lang.Object[] java.util.ArrayList.EMPTY_ELEMENTDATA
private static final java.lang.Object[] java.util.ArrayList.DEFAULTCAPACITY_EMPTY_ELEMENTDATA
transient java.lang.Object[] java.util.ArrayList.elementData
private int java.util.ArrayList.size
private static final int java.util.ArrayList.MAX_ARRAY_SIZE
*/
Copy the code
Method of operation
Method[] getMethods()
: Gets all the exposed methods of a class, including the parent classMethod[] getDeclaredMethods()
: Gets all the methods in a class, excluding the parent classMethod getMethod(String name, Class<? >... parameterTypes)
: Gets the specified, public method of the classMethod getDeclaredMethod(String name, Class<? >... parameterTypes)
: gets the method specified in the classString getName()
: Gets the name of the methodvoid setAccessible(boolean flag)
: Indicates whether the user has the access permission for the methodObject invoke(Object obj, Object... args)
: Calls this method, passing the argument list
ArrayList<Integer> integers = new ArrayList<>();
Method add = integers.getClass().getDeclaredMethod("add", Object.class);
add.setAccessible(true);
add.invoke(integers, 120);
System.out.println(integers.get(0));
for (Method method : integers.getClass().getMethods()) {
System.out.println(method);
}
/* 120 public boolean java.util.ArrayList.add(java.lang.Object) public void java.util.ArrayList.add(int,java.lang.Object) public boolean java.util.ArrayList.remove(java.lang.Object) public java.lang.Object java.util.ArrayList.remove(int) public java.lang.Object java.util.ArrayList.get(int) public boolean java.util.ArrayList.equals(java.lang.Object) public int java.util.ArrayList.hashCode() public java.lang.Object java.util.ArrayList.clone() ............ * /
Copy the code
It is worth noting that invoke(Object obj, Object… The obj argument can be set to null if args) calls static methods
Instance objects
Reflection can not only access and manipulate properties and methods, but also instantiate objects
T newInstance()
: calls the no-argument construction of the class
Type judgment
boolean isArray()
: Indicates whether it is an arrayboolean isPrimitive()
: Indicates whether it is an original typeboolean isInterface()
: Indicates whether it is an interfaceisEnum()
: Indicates whether to enumerateisAnnotation()
: Indicates whether it is an annotationisAnonymousClass()
: Indicates whether it is an anonymous inner classisMemberClass()
: Indicates whether it is a member inner classisLocalClass()
: Whether it is a local class, that is, a local inner class
System.out.println(ArrayList.class.isArray());
System.out.println(ArrayList.class.isPrimitive());
System.out.println(ArrayList.class.isInterface());
System.out.println(ArrayList.class.isEnum());
System.out.println(ArrayList.class.isAnnotation());
System.out.println(ArrayList.class.isAnonymousClass());
System.out.println(ArrayList.class.isMemberClass());
System.out.println(ArrayList.class.isLocalClass());
/*
false
false
false
false
false
false
false
false
*/
Copy the code
Declaration of a class
int getModifiers()
: Gets a class modifier that returns a hexadecimal text numberClass<? super T> getSuperclass()
: Gets the parent class that the class inheritsClass<? >[] getInterfaces()
: Gets the interface implemented by the classAnnotation[] getDeclaredAnnotations()
: Gets an annotation of the class declarationAnnotation[] getAnnotations()
: Gets annotations of the class declaration, including the parent class
// getModifiers() get hexadecimal text numbers for modifiers PUBLIC = 0x00000001; ABSTRACT = 0x00000400
System.out.println(ArrayList.class.getModifiers());
System.out.println(AbstractList.class.getModifiers());
/* 1,1025 */
// Get the parent of the current class. The parent of Object is null
System.out.println(ArrayList.class.getSuperclass());
/* class java.util.AbstractList */
// Get the interface implemented by the current class, return an array
System.out.println(Arrays.toString(ArrayList.class.getInterfaces()));
/* [interface java.util.List, interface java.util.RandomAccess, interface java.lang.Cloneable, interface java.io.Serializable] */
Copy the code
The inner class
Class<? >[] getClasses()
: Gets all exposed inner classes, interfaces, including parent classesClass<? >[] getDeclaredClasses()
: Gets all inner classes and interfaces, excluding the parent classClass<? > getDeclaringClass()
If the current class is an inner class, get its outermost outer classClass<? > getEnclosingClass()
: Gets the directly contained outer class if the current class is an inner classMethod getEnclosingMethod()
: Returns a method in an anonymous, local inner class
System.out.println(Arrays.toString(ArrayList.class.getClasses()));
/ * * / []
System.out.println(Arrays.toString(ArrayList.class.getDeclaredClasses()));
/* [ class java.util.ArrayList$ArrayListSpliterator, class java.util.ArrayList$SubList, class java.util.ArrayList$ListItr, class java.util.ArrayList$Itr ] */
Copy the code
Class loading
Class<? > forName(String className)
: Loads the class file according to the fully qualified nameClass<? > forName(String name, boolean initialize, ClassLoader loader)
Load the class file and do some Settingsinitialize
: Whether to initialize the code block. Default is trueloader
: class loader. Default is currentLoader
In the previous three ways reflection was created, time has run out and I won’t demonstrate it here
Class loaders, not necessary for now, but explained later
Primitive types are not supported in class loading, i.e. forName() cannot be used