Reflection is often used in our work. Today, we will systematically sort out the knowledge points of reflection. Here are several modules to sort out the content of reflection.
Acquisition method of Class
-
Obtained by class name. class
Class clazz = Animal.class;
-
Obtained through the object. getClass method
Cat cat = new Cat(); Class aClass = cat.getClass();
-
Get by class name
try { Class<?> aClass1 = Class.forName("com.example.testreflect.Animal"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
Note: Although there are many ways to obtain, class objects are unique in memory, so objects locked by static methods are class objects.
Some methods of class objects, taking String as an example:
method | effect |
---|---|
getName() | Get the full name of the class with the package name (java.lang.String) |
getSimpleName() | Get the name of the class without the package name (String) |
getPackage().getName() | Get package name (java.lang) |
isInterface() | Is it an interface (not an interface) |
isEnum() | Whether it is an enumeration (not an enumeration) |
isArray() | Is it an array (not an array) |
isPrimitive() | Whether it is a basic type (not a basic type) |
newInstance() | To create a class instance, you can only call public parameterless construction methods. |
Some tips to determine whether a class exists
boolean isClassPresent(String name) { try { Class.forName(name); return true; } catch (Exception e) { return false; } }
Field Access
- How to get the field:
method | effect |
---|---|
Field getField(name) | Get the field of a public according to the field name (including the parent class) |
Field getDeclaredField(name) | Obtain a field of the current class according to the field name. Private can also be used (excluding the parent class) |
Field[] getFields() | Get all public field s (including the parent class) |
Field[] getDeclaredFields() | Get all the field s of the current class, or private ones (excluding the parent class) |
Test and operation results
public void filedId() throws NoSuchFieldException { Class<Cat> catClass = Cat.class; Field age = catClass.getField("age"); Field name = catClass.getField("name"); Field climb = catClass.getDeclaredField("climb"); Field[] fields = catClass.getDeclaredFields(); Field[] fields1 = catClass.getFields(); System.out.println(age + "\n" + name + "\n" + climb + "\n" + Arrays.toString(fields) + "\n" + Arrays.toString(fields1)); }
Running results
I System.out: public int com.example.testreflect.Animal.age I System.out: public java.lang.String com.example.testreflect.Animal.name I System.out: private int com.example.testreflect.Cat.climb I System.out: [private int com.example.testreflect.Cat.climb] I System.out: [public int com.example.testreflect.Animal.age, public java.lang.String com.example.testreflect.Animal.name]
- Some methods of Field
method | effect |
---|---|
getName() | Return Field Name |
getType() | Returns the field type, which is also a Class instance |
getModifiers() | Returns the modifier of a field. It is an int. Different bit s represent different meanings. |
Field test:
Field f = String.class.getDeclaredField("value"); f.getName(); // "value" f.getType(); // class [B indicates byte [] type int m = f.getModifiers(); Modifier.isFinal(m); // true Modifier.isPublic(m); // false Modifier.isProtected(m); // false Modifier.isPrivate(m); // true Modifier.isStatic(m); // false
- Get Object Field Value
class Test{ public void getValue() throws NoSuchFieldException, IllegalAccessException { Animal animal = new Animal(1, "cockroach"); Class<? extends Animal> aClass = animal.getClass(); Field name = aClass.getDeclaredField("name"); //The setAccessible function is to enable and disable the access security check name.setAccessible(true); Object o = name.get(animal); System.out.println(o);//cockroach } } class Animal{ private int age; private String name; public Animal(int age, String name) { this.age = age; this.name = name; } }
Note that the above access is to the private properties of Animal. You must disable the access security check to access setAccessible.
-
Set Object Field Values
class Test{ @Test public void setValue() throws NoSuchFieldException, IllegalAccessException { Animal animal = new Animal(1, "cockroach"); Class<? extends Animal> aClass = animal.getClass(); Field name = aClass.getDeclaredField("name"); //The setAccessible function is to enable and disable the access security check name.setAccessible(true); name.set(animal,"Xiao Ming"); Object o = name.get(animal); System.out.println(o);//Xiao Ming } } class Animal{ private int age; private String name; public Animal(int age, String name) { this.age = age; this.name = name; } }
Method call
-
Method call
method effect Method getMethod(name, Class...) Get the Method of a public (including the parent class) Method getDeclaredMethod(name, Class...) Get a Method of the current class (excluding the parent class) Method[] getMethods() Get all public methods (including the parent class) Method[] getDeclaredMethods() Get all methods of the current class (excluding the parent class) Test Code
class Test{ public void call() throws NoSuchMethodException { Class<Cat> catClass = Cat.class; //Get the getAge of public. The parameter is of String type Method getAge = catClass.getMethod("getAge", String.class); //Get the getNameByTag of public. The parameter is of type int Method getNameByTag = catClass.getMethod("getNameByTag", int.class); // Get the private method getClimb, Method getClimb = catClass.getDeclaredMethod("getClimb"); } } class Animal{ private int age; private String name; public String getNameByTag(int tag) { return name + tag; } public int getAge(String type) { return age; } } class Cat extends Animal{ private int climb; private int getClimb() { return climb; } }
-
Method method
method effect getName() Return Method Name getReturnType() The return value type of the return method is also a Class instance getParameterTypes() The parameter type of the return method, which is a Class array getModifiers() Modifier of return method, which is an int, and different bit s represent different meanings -
Reflection call method
The first parameter of invoke is the object instance, that is, the instance on which the method is called. The following variable parameters must be consistent with the method parameters, or an error will be reported.
public void invoke() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Cat cat = new Cat(); cat.setName("cockroach"); Class<? extends Cat> aClass = cat.getClass(); Method getNameByTag = aClass.getMethod("getNameByTag", int.class); Object invoke = getNameByTag.invoke(cat, 1); System.out.println(invoke);//Xiaoqiang 1 }
-
Static method call
The obtained Method represents a static method. When calling a static method, the first parameter passed in by the invoke method is always null because there is no need to specify an instance object.
public void callStaticMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method test = Animal.class.getMethod("test"); //The caller passes null directly. Object invoke = test.invoke(null); }
-
Private method call
In order to call non public methods, we allow them to call through Method.setAccessible(true).
public void invokePrivateMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Animal animal = new Animal(); animal.setName("cockroach"); Class<Animal> animalClass = Animal.class; Method getName = animalClass.getDeclaredMethod("getName"); getName.setAccessible(true);//getName is a private method Object invoke = getName.invoke(animal); System.out.println(invoke);//cockroach }
Note: setAccessible(true) may fail. If there is a SecurityManager in the JVM runtime, it will check according to the rules, which may prevent setAccessible(true). For example, a SecurityManager may not allow setAccessible(true) to be called on package classes starting with java and javax, which can ensure the security of the JVM core library.
-
Polymorphic thinking
The parent class gets the method and the child class executes it. When using reflection to call the method, it still follows the polymorphism principle.
The following test program prints cat.
class Test{ public void duotai() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { Cat cat = new Cat(); Method eat = cat.getClass().getDeclaredMethod("eat"); eat.invoke(cat); } } class Animal{ public void eat(){ System.out.println("animal"); } } class Cat extends Animal{ @Override public void eat() { System.out.println("cat"); } }
Construction method call
-
Call public parameterless constructor
Animal animal = Animal.class.newInstance();
-
In order to call any constructor, Java's reflection API provides the Constructor object, which contains all the information of a constructor and can create an instance.
class{ public void invokeC() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class<Animal> aClass = Animal.class; Constructor<Animal> constructor = aClass.getConstructor(String.class, int.class); Animal animal = constructor.newInstance("cockroach", 2); System.out.println(animal.getAge() + "--" + animal.getName());//2 -- Xiaoqiang } } class Animal{ private String name; private int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat(){ System.out.println("animal"); } public String getName() { return name; } public int getAge() { return age; } }
-
Summary of construction methods
method effect getConstructor(Class...) Get a public Constructor getDeclaredConstructor(Class...) Get a Constructor getConstructors() Get all public constructors getDeclaredConstructors() Get all constructors Note: When calling a non public Constructor, you must first allow access through the setAccessible(true) setting. setAccessible(true) may fail.
Inheritance relationship
The class instance can obtain the class of its parent class by calling getSuperclass(), and the interface type it implements can be obtained by calling getInterfaces.
Note: etInterfaces() only returns the interface type directly implemented by the current class, not including the interface type implemented by its parent class
Dynamic Proxy
As we all know, class (non abstract) can create objects, while interface cannot be instantiated. One of the java development specifications is interface oriented programming. In fact, it is transformed upward through an instance and assigned to interface type variables.
The dynamic proxy does not need to write an implementation class, but directly creates an instance of an interface during the runtime.
Dynamic proxy is a proxy provided directly through JDK NewProxyInstance () creates an interface object, which is created during runtime and is also generated in memory.
It is used as follows:
The method to dynamically create an interface instance during runtime is as follows:
-
Define an InvocationHandler instance, which is responsible for implementing the method call of the interface;
-
Create an interface instance through Proxy.newProxyInstance(), which requires three parameters:
-
The ClassLoader used is usually the ClassLoader of the interface class;
-
The interface array to be implemented must be passed in at least one interface;
-
InvocationHandler instance used to process interface method calls.
-
-
Force the returned Object into an interface.
class Test{ public void testProxy(){ InvocationHandler invocationHandler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method + "--" + Arrays.toString(args));// public abstract void com.example.testreflect.Action.eat(java.lang.String)--[fruit] return null; } }; Action action = (Action) Proxy.newProxyInstance(Action.class.getClassLoader(), new Class[]{Action.class}, invocationHandler); action.eat("fruit"); } } interface Action { void eat(String food); }