The Java reflection mechanism is in the running state, for any class, can know all the properties and methods of this class, for any object, can invoke its arbitrary methods and properties; This dynamic acquisition of information and the ability to dynamically invoke object methods is called the reflection mechanism of the Java language.
A: Class
In an object-oriented world, everything is object. The class is also an object, and the class is an instance object of the Java.lang.Class class.
Instances of class classes represent classes and interfaces in a running Java application. An enumeration is a class, and a comment is an interface. Each array belongs to a class that is mapped to a class object, and all arrays that have the same element type and number of dimensions share the class object.
The basic Java types (,,,,,, boolean byte char short int long float and double ) and keywords void are also represented as Class objects.
Class has no public constructor method. Class objects are constructed automatically by the Java virtual machine and by calling methods in the class loader when the class is loaded defineClass .
The above comes from the JDK, Luo Li, the following I would say that their own experience:
Class is not abstract, class is concrete!
Class is a. Class bytecode file, to get a class instance object, you first need to get the. Class bytecode file!
Then call some methods of class object, make dynamic get information and call object method dynamically!
II: Class type
Create a new Foo class. Foo This class is also an instance object, which is an instance object of class.
I do not know if you care about the declaration of the class and the statement of the method:
public class Foo{ Foo(){ //构造方法 }}public Foo method(){ //...}
We know that the public is followed by the return type, and we know that class is also a type.
How do I represent an instance object of class?
public static void main(String[] args) { //Foo的实例对象,new 就出来了 Foo foo1 = new Foo(); //如何表示? //第一种:告诉我们任何一个类都有一个隐含的静态成员变量class Class c1 = Foo.class; //第二种:已经知道该类的对象通过getClass方法 Class c2 = foo1.getClass(); System.out.println(c1 == c2); //第三种:动态加载 Class c3 = null; try { c3 = Class.forName("cn.zyzpp.reflect.Foo"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c2 == c3); }
The above print results are alltrue
Although C1 or C2 all represent the class type of Foo, a class can only be an instance variable of the class.
We can create an instance object of the class from the class type (class type) entirely.
//此时c1 c2 c3为Class的实例对象 try {// Foo foo = (Foo)c1.newInstance(); Foo foo = (Foo)c3.newInstance(); foo.print(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
Static loading
The new creation object is a static load class, and all of the possible classes need to be loaded at compile time.
Dynamic loading
Use Class.forName (the full name of the class) to load the class name as a dynamic load.
The compile-time load class is a static load class, and the run-time load class is a dynamic load class.
As an example,
Defining Office Classes
public class Office { public void print() { System.out.println("office"); }}
Defining the Loading class
public class Loading { public static void main(String[] args) { try { //在运行时再动态加载类 //arg[0] 为java执行命令时传的参数 Class<?> a = Class.forName(args[0]); Office office = (Office) a.newInstance(); office.print(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } }}
Execution process
D:\>javac -encoding utf-8 Loading.java Office.javaD:\>java Loading Officeoffice
Class a=Class.forName(arg[0])get the class by dynamic loading, because compile-time does not know which class to use, so the compilation does not load any classes, directly through compile, run, according to java Loading Office (Office is a class type/class, subscript arg[0]), to determine which class A is. This is dynamic loading. If the Office class does not exist, running at this point will cause an error. That's why there are times when compiling passes and running an error.
One benefit of dynamic loading is that you can add classes that need to be compiled at any time. For example, transform office into an abstract class or interface, define different subclasses, and dynamically select load.
Three: Reflection of a class
With the above three methods to get to the class type, you can get to the class's member methods, member variables, method parameter comments and other information.
A method object is a methods class, and a member method is an object.
| Method |
explain |
getMethods() |
Returns an array of methods for the class's inheritance and all public declarations of its own |
getDeclaredMethods() |
Returns an array of methods for all public that the class itself declares, not including inherited |
Member variables are also objects, which are Java.lang.reflect.Field objects, and the field class encapsulates operations on member variables.
| Method |
explain |
getFields() |
Gets the member variable information for all public, including inherited. |
getDeclaredFields() |
Gets the member variable information that the class itself declares, Public,private, and so on |
Gets the int return value of the Java language modifier (public, private, final, Static), and then invokes the Modifier.toString() string form of the Get modifier, noting that the method returns all modifiers.
| Method |
explain |
getModifiers() |
Returns the Java language modifier for the field represented by this object as an integer. |
Get comments
| Method |
explain |
getAnnotations() |
Returns all comments that exist on this element. |
getDeclaredAnnotations() |
Returns all comments that exist directly on this element. |
Constructors are also objects, objects that are java.lang.reflect.Constructor.
| Method |
explain |
getConstructors() |
Returns all public constructor methods |
getDeclaredConstructors() |
Returns all constructor methods for a class, more than public |
Complete example
private void Printclassmessage (Object obj) {//To get the information of the class, first get the class type of class Clazz = Obj.getclass (); Gets the name of the class System.out.println (Modifier.tostring (Clazz.getmodifiers ()) + "" + Clazz.getclass (). GetName () + "" +clazz.getn Ame () + "{"); SYSTEM.OUT.PRINTLN ("----construction method----"); Construction method constructor[] constructors = clazz.getdeclaredconstructors (); for (Constructor constructor:constructors) {//constructor method modifier with name System.out.print (modifier.tostring (constru Ctor.getmodifiers ()) + "" +constructor.getname () + "("); All parameter types of the constructor class[] parametertypes = Constructor.getparametertypes (); for (Class c:parametertypes) {System.out.print (C.getname () + ","); } System.out.println (") {}"); } System.out.println ("----member variable----"); Member Variable field[] fields = Clazz.getdeclaredfields (); for (Field field:fields) {SYSTEM.OUt.println ("+modifier.tostring (Field.getmodifiers ()) +" "+field.gettype (). GetName () +" "+ field.getname () +"; "); } System.out.println ("----Member method----"); Method class, methods object, a member method is an object method[] methods = Clazz.getdeclaredmethods (); For (method Method:methods) {//Get method return type Class returntype = Method.getreturntype (); Gets all comments on the method annotation[] annotations = method.getannotations (); for (Annotation annotation:annotations) {//Print note type System.out.println ("@" +annotation.annota Tiontype (). GetName () + ""); }//Print method declaration System.out.print ("" +modifier.tostring (Returntype.getmodifiers ()) + "" +returntype.getname ( ) + "" +method.getname () + "("); Gets all parameter types of the method class<?>[] parametertypes = Method.getparametertypes (); Gets all parameters of the method parameter[] Parameters = Method.getparameters (); for (PaRameter parameter:parameters) {//parameter type, formal parameter (all arg123). ) System.out.print (Parameter.gettype (). GetName () + "" +parameter.getname () + ","); } System.out.println (")"); } System.out.println ("}"); }
As an example of a string object, print the result:
public final java.lang.Class java.lang.String{----构造方法----public java.lang.String([B, int, int, ){} java.lang.String([C, boolean, ){}----成员变量---- private final [C value; private int hash;----成员方法---- @java.lang.Deprecated public abstract final void getBytes(int arg0, int arg1, [B arg2, int arg3, ) ......}
IV: Reflection of the method
Defines a class Foo for testing
public class Foo{ public void print(String name,int num) { System.out.println("I am "+name+" age "+num); }}
Target: Get the method by reflection, pass in the parameter, execute the method!
1. The method to get the class is to get the information of the class, get the class information first to get the class type
Class clazz = Foo.class;
2. Get method objects by name + parameter type
Method method = clazz.getMethod("print", new Class[]{String.class,int.class});
3. The method's reflection operation is called by the method object to achieve the same effect as the new Foo (). Print ()
method returns null if no return value is returned
Object o = method.invoke(new Foo(),new Object[]{"name",20});
V: Understanding generics through reflection
public static void main(String[] args) { ArrayList<String> stringArrayList = new ArrayList<>(); stringArrayList.add("hello"); ArrayList arrayList = new ArrayList(); Class c1 = stringArrayList.getClass(); Class c2 = arrayList.getClass(); System.out.println(c1 == c2); }
Prints the result astrue
The result of the C1==C2 returns a description of the generic type of the collection after compilation is de-generalized. In other words, generics are different and have no effect on types.
Generics in Java are only intended to prevent erroneous input, only valid during the compile phase, and bypassing compilation is not valid.
Verify
We can manipulate by reflection, bypassing compilation.
public static void main(String[] args) { ArrayList<String> stringArrayList = new ArrayList<>(); stringArrayList.add("hello"); ArrayList arrayList = new ArrayList(); Class c1 = stringArrayList.getClass(); Class c2 = arrayList.getClass(); System.out.println(c1 == c2); try { Method method = c1.getMethod("add",Object.class); method.invoke(stringArrayList,20); System.out.println(stringArrayList.toString()); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
Printing results:
true[hello, 20]
The constraints of generic <String> were successfully bypassed.