First, the basic concept of reflection
Reflection contains an "inverse" concept, so to explain the reflection must first start from "positive", in general, when the user uses a class, should know the class, and then through the class to produce instantiated objects, but "anti" refers to the object to find the class.
packagecn.mldn.demo;class Person { }public class TestDemo { public static void main(String[] args) throws Exception { Person per = new Person(); // 正着操作 System.out.println(per.getClass().getName()); // 反着来 }}
The above code uses a GetClass () method, and then can get the "package. Class" Name of the object, which is "anti", but in this "counter" operation there is a getclass () as the beginning of all the reflection operations initiated.
The parent class of person is the object class, and the GetClass () method used above is the method defined in the object class.
Get Class object: Public final class<?> getclass (), all generics in reflection are defined as?, and the return value is object. The object returned by this getclass () method is the object of class, so this class is the source of all the reflection operations. But there is one more question to explain before explaining its true use, since class is the source of all reflection operations, and this class is certainly the most important, if you want to get instantiated objects of this class.
Three ways are defined in Java:
- Method One: Obtained by means of the GetClass () method of the object class, basically without:
packagecn.mldn.demo;class Person {}public class TestDemo { public static void main(String[] args) throws Exception { Person per = new Person(); // 正着操作 Class<?> cls = per.getClass(); // 取得Class对象 System.out.println(cls.getName()); // 反着来 }}
- Mode two: Use "class. Class" To be used in the future when learning hibernate development
packagecn.mldn.demo;class Person {}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Person.class; // 取得Class对象 System.out.println(cls.getName()); // 反着来 }}
packagecn.mldn.demo;class Person {}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 System.out.println(cls.getName()); // 反着来 }}
So now a new question has come, what is the use of the class object? The instantiation of an object has been done by using the constructor method and the keyword new, but with the class object, it now provides an instantiation of another object:
To instantiate an object by reflection:
public T newInstance() throws InstantiationException,IllegalAccessException;
Example: Instantiating an object by reflection
packagecn.mldn.demo;class Person { @Override publicString toString() { return "Person Class Instance ."; }}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 Object obj = cls.newInstance(); // 实例化对象,和使用关键字new一样 Person per = (Person) obj; // 向下转型 System.out.println(per); }}
Now it can be found that the instantiation of the object, in addition to using the keyword new, there is a reflection mechanism operation, and this operation is more complex than the previous use of new, but what is the use?
Before the program's development model has been emphasized: minimize coupling, and the best way to reduce coupling is to use the interface, but even if the use of interfaces can not escape the keyword new, so in fact, new is the key to create coupling.
Example: Review the factory design pattern you wrote earlier
packagecn.mldn.demo;interface Fruit { public void eat();}class Apple implements Fruit { public void eat() { System.out.println("吃苹果。"); }}class Factory { public static Fruit getInstance(String className) { if ("apple".equals(className)) { return new Apple(); } return null; }}public class FactoryDemo { public static void main(String[] args) { Fruit f = Factory.getInstance("apple"); f.eat(); }}
These are the simplest factory design patterns that have been written before, but one of the biggest problems in this factory design pattern is that if the subclass of the interface now increases, then the factory class will need to be modified, which is the biggest problem it faces, and the key cause of the biggest problem is new, So what if we don't use the keyword new now and become a reflection mechanism?
When the reflection mechanism instantiates an object, it actually only needs "package. Class" To do so, and according to this operation, modify the factory design pattern.
packagecn.mldn.demo;interface Fruit { public void eat();}class Apple implements Fruit { public void eat() { System.out.println("吃苹果。"); } ;}class Orange implements Fruit { public void eat() { System.out.println("吃橘子。"); }}class Factory { public static Fruit getInstance(String className) { Fruit f = null; try { f = (Fruit) Class.forName(className).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; }}public class FactoryDemo { public static void main(String[] args) { Fruit f = Factory.getInstance("cn.mldn.demo.Orange"); f.eat(); }}
Found that this time even if the sub-class of the interface is added, the factory class can still complete the object instantiation operation, this is the real factory class, can be applied to all changes. If there is little relationship with the developer from the point of view of development, but for the future study of some framework technology this is the lifeblood of its realization, in the future development of the program, if you find the process needs to pass a complete "package. Class" Name is almost the reflection mechanism of action.
Second, the deep application of reflection
The above only uses the class as the basic application of the reflection instantiation object, but for an instantiated object, it needs to invoke the constructor method, the common method, the property in the class, and these operations can be done through the reflection mechanism.
1. Call constructs to use
The reflection mechanism can also be used to construct methods within classes, which have been explicitly defined in the class class: The following two methods obtain all constructs of a class:
Public constructor<?>[] GetConstructors () throws
SecurityException
Gets the specified argument construct for a class:
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
It is now found that the above two methods return objects of the Java.lang.reflect.Constructor class.
Example: Get all constructs in a class
packagecn.mldn.demo;import java.lang.reflect.Constructor;class Person { // CTRL + K public Person() { } public Person(String name) { } public Person(String name, intage) { }}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 Constructor<?> cons[] = cls.getConstructors(); // 取得全部构造 for (intx = 0; x < cons.length; x++) { System.out.println(cons[x]); } }}
Validation: A simple Java class that was previously emphasized must have an parameterless construction method
Example: observing a condition without an argument structure
packagecn.mldn.demo;class Person { // CTRL + K private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; }}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 Object obj = cls.newInstance(); // 实例化对象 System.out.println(obj); }}
At this time the program ran with the error "java.lang.InstantiationException", because the above way to use reflection to instantiate the object needs to provide a non-parametric construction method, but now since there is no parameterless construction method, Then you must explicitly find a construction method and then instantiate the object with a new method in the constructor class:
Instantiating an object:
public T newInstance(Object...initargs) throws InstantiationException, IllegalAccessException,IllegalArgumentException,InvocationTargetException
packagecn.mldn.demo;import java.lang.reflect.Constructor;class Person { // CTRL + K private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; }}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 // 取得指定参数类型的构造方法 Constructor<?> cons = cls.getConstructor(String.class, int.class); Object obj = cons.newInstance("张三", 20); // 为构造方法传递参数 System.out.println(obj); }}
It is obvious that it is simpler and more convenient to invoke the parameterless construction method than to invoke the parameter structure, so in all future development, there must be a non-parametric structure in all the areas where there are simple Java classes.
2, call the common method
When a class instantiation object is obtained, the following is definitely the method within the class that is most needed to invoke, so you can continue to use the class class to get the method definition defined in a class:
Get all the methods:
public Method[] getMethods() throws SecurityException;
Get the specified method:
public Method getMethod(Stringname, Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
It is found that the above methods return objects of the Java.lang.reflect.Method class.
Example: Get all the methods defined in a class
packagecn.mldn.demo;importjava.lang.reflect.Method;class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; }}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 Method met[] = cls.getMethods(); // 取得全部方法 for (intx = 0; x < met.length; x++) { System.out.println(met[x]); } }}
However, the maximum effect of the method object is no longer in the list of methods (the list of methods is used on the development tools), but there is also one of the most important functions after obtaining the method object, which is to invoke the methods in the class with reflection:
Call Method:
public Object invoke(Object obj, Object... args) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
Before invoking a method in a class, you are using the object. method, but now that you have reflection, you can invoke the action method of the specified subclass directly using the object class. (also explain why the naming requirements for setter and getter methods are so strict).
Example: Invoking the SetName (), GetName () method in the person class with reflection
Packagecn.mldn.demo;import java.lang.reflect.method;class person {private String name; public void SetName (String name) {this.name = name; } public String GetName () {return name; }}public class Testdemo {public static void main (string[] args) throws Exception {class<?> CLS = class.f ORName ("Cn.mldn.demo.Person"); Gets the class object obj = Cls.newinstance (); Instantiating an object without transitioning to person String attribute = "name"; To invoke a property within a class, Method Setmet = Cls.getmethod ("Set" + Initcap (attribute), string.class);//SetName () method get Met = Cls.getmethod ("Get" + Initcap (attribute));//GetName () setmet.invoke (obj, "Zhang San"); Equivalent to: Person object. SetName ("Zhang San") System.out.println (Getmet.invoke (obj));//equivalent to: Person object. GetName ()} public Stati C string Initcap (String str) {return str.substring (0, 1). toUpperCase (). Concat (str.substring (1)); }}
In all future framework technology development, the simple Java class is so applied, so it must be done according to the standard.
3. Call the last component of the Member class
is a member (Field, also called a property), if you want to get a member of the class through reflection, you can use the following method:
Obtain all members of this class:
public Field[] getDeclaredFields() throws SecurityException;
Gets the specified member:
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException;
The return value type of the two methods is an object of the Java.lang.reflect.Field class, and the following first observes how to get all the properties in a class.
Example: Get all the properties in a class
packagecn.mldn.demo;import java.lang.reflect.Field;class Person { private String name;}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 Field field[] = cls.getDeclaredFields(); // 取得全部属性 for (intx = 0; x < field.length; x++) { System.out.println(field[x]); } }}
But finding field actually found a very interesting operation, with two methods in the field class:
Sets the property content (similar to: object. property = content): public void Set (Object obj,
Object value) throws
IllegalArgumentException, illegalaccessexception;
Gets the property content (similar to: Object. Properties): Public object Get (object obj) throws
IllegalArgumentException, illegalaccessexception but from the development requirements of the class, it has always been emphasized that the attributes within the class must be encapsulated, so it is time to remove the encapsulation before calling.
To release the package:
public voidsetAccessible(boolean flag) throws SecurityException;
Example: Taking advantage of properties in a reflection action class
packagecn.mldn.demo; import java.lang.reflect.Field;class Person { private String name;}public class TestDemo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 Object obj = cls.newInstance(); // 对象实例化属性才会分配空间 Field nameField = cls.getDeclaredField("name"); // 找到name属性 nameField.setAccessible(true); // 解除封装了 nameField.set(obj, "张三"); // Person对象.name = "张三" System.out.println(nameField.get(obj)); // Person对象.name }}
Transferred from: https://www.zhihu.com/question/24304289/answer/38218810
How do I understand Java reflection?