Java reflection is a very powerful mechanism for detecting fields, methods, and constructors of internal classes in the same system. It has a lot of reflection in its Java frameworks, such as Hibernate and Spring. Arguably, the nature of reflection allows Java to build incredibly powerful, flexible systems.
This article is shared by Jackwangcumt from The Huawei Cloud community “JAVA Programming indispensable Reflection usage summary” [Running! JAVA].
Java reflection is a very powerful mechanism for detecting fields, methods, and constructors of internal classes in the same system. It has a lot of reflection in its Java frameworks, such as Hibernate and Spring. Arguably, the nature of reflection allows Java to build incredibly powerful, flexible systems.
While Java reflection has its drawbacks of low efficiency, slow speed, and low security, there are many scenarios where these characteristics are not a major factor or where execution efficiency can be progressively improved through caching or JVM optimizations.
Reflection is an advanced language feature and a powerful technique that enables applications to do things that would otherwise be impossible, according to the web.
The following illustrates and summarizes the basics of Java reflection:
Start by defining a MyBase class with both private and public fields. There are also public and private methods. The following is an example of the MyBase class:
package com.hwdev.demo; /** * @author wangming */ public class MyBase {// public int version = 1; // Private String date = "2021-05-18"; Public void say2(String MSG){system.out.println ("Hello "+ MSG); } // Private String getData(){return this.date; }}Copy the code
Here we define a Hello class, which inherits from MyBase class, mainly used to verify the use of reflection for parent and child classes.
package com.hwdev.demo; /** * * @author wangming */ public class Hello extends MyBase { public String author = "JackWang" ; public int version = 1; private String company = "kzcloud" ; public void say(String msg){ System.out.println("Hello " + msg); } public void setAuthor(String author){ this.author = author; } public String getAuthor(){ return this.author; } private int getVersion(){ return this.version; }}Copy the code
The most powerful thing about Java reflection is that you can use string configuration to dynamically call a method from the system or change the field value of one of the objects. The class.forname method can get the corresponding Class object by passing in the Class full path string name, which is very convenient. In addition, the getField method and GetMethod methods can obtain the specified field and method, and dynamic call.
package com.hwdev.demo; import java.lang.reflect.*; import java.util.Arrays; Public Class ReflectDemo01 {public static void Test() {try { Class helloC = class.forname (" com.hwdev.demo.hello "); [] fields = helloc.getFields (); Field [] fields = helloc.getFields (); System.out.println(arrays.toString (fields)); //[public java.lang.String com.hwdev.demo.Hello.author, Public int com. Hwdev. Demo. Hello. Version] / / instantiate the Object obj = helloC. NewInstance (); Field f = helloc.getField ("author"); if (f ! F.setaccessible (true); = null){// Turn off security checks to improve efficiency. String author = (String) f.et (obj); System.out.println("author=" + author); [] methods = helloc.getMethods (); System.out.println(arrays.toString (methods)); / / this class all Method [] methods2. = helloC getDeclaredMethods (); System.out.println(array.toString (methods2)); M = helloc.getDeclaredMethod ("say", string.class); m = helloc.getDeclaredMethod ("say", string.class); if (m ! = null){// Turn off security check, improve efficiency m.setaccessible (true); Object returnValue = m.invoke(obj, new Object[]{"Java"}); //Hello Java if (returnValue! =null){ System.out.println("returnValue =" + returnValue); } } }catch(ClassNotFoundException | SecurityException ex){ ex.printStackTrace(); } catch(Exception ex){ ex.printStackTrace(); }}}Copy the code
By default, xxx.getMethods() returns public methods of the class, parent, and parent interface, while xxx.getDeclaredMethods() returns all methods of the class, including private methods. Similarly, the other getXXX and getDeclaredXXX in the reflection API are used similarly.
package com.hwdev; import com.hwdev.demo.ReflectDemo01; /** * * @author wangming */ public class Main { /** * @param args the command line arguments */ public static void Main (String[] args) {// ReflectDemo01.test (); }}Copy the code
Execute the program and the output is as follows:
[public java.lang.String com.hwdev.demo.Hello.author, public int com.hwdev.demo.Hello.version, public int com.hwdev.demo.MyBase.version]
author=JackWang
[public void com.hwdev.demo.Hello.say(java.lang.String), public void com.hwdev.demo.Hello.setAuthor(java.lang.String), public java.lang.String com.hwdev.demo.Hello.getAuthor(), public void com.hwdev.demo.MyBase.say2(java.lang.String), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
[public void com.hwdev.demo.Hello.say(java.lang.String), public void com.hwdev.demo.Hello.setAuthor(java.lang.String), public java.lang.String com.hwdev.demo.Hello.getAuthor(), private int com.hwdev.demo.Hello.getVersion()]
Hello Java
Copy the code
Field [] fields = helloc.getFields (); Field [] fields = helloc.getFields (); Not only can get the Hello class of public fields, you can also get to the parent class MyBase public fields: com. Hwdev. Demo. MyBase. Version
The Method [] methods2. = helloC getDeclaredMethods (); You can get all the methods of this class, that is, the Hello class, including public and private methods. Therefore, Java reflection can access the private fields and methods of a class, exposing internal information, which is why Java reflection is a security problem.
Because Java methods support overloading, multiple methods with the same name can exist, that is, with different parameters. Therefore, when using reflection to call a method, you need to specify the parameter type of the method, so that you can clearly call the specific method signature. M = helloc.getdeclaredMethod (“say”, string.class); Public void com.hwdev.demo.hello. Say (java.lang.String)
In addition to using Class. ForName to reflect objects, you can also use the following methods:
Hello hello = new Hello();
Class helloC = hello.getClass();
Field [] fields = helloC.getFields();
//////////////////////////////////////////
Class helloC = Hello.class;
Field [] fields = helloC.getFields();
Copy the code
Here is an example of how to use Java reflection to modify private fields and call private methods:
package com.hwdev.demo; import java.lang.reflect.*; /** * Reflection access private fields and methods * @author wangming */ public class ReflectDemo02 {public static void Test() {try Class helloC = Hello.class; // Instantiate Object obj = helloc.newinstance (); Field f = helloc.getDeclaredField ("company"); if (f ! = null){// Private must turn on f.setaccessible (true); // set the private field value f.et (obj, "newKZ"); String fv = (String) f.et (obj); System.out.println("company=" + fv); M = helloc.getDeclaredMethod ("getVersion", null); if (m ! = null){// Private must be enabled m.setaccessible (true); Object returnValue = m.invoke(obj, null); if (returnValue! =null){ //returnValue =1 System.out.println("returnValue =" + returnValue); } } }catch(SecurityException ex){ ex.printStackTrace(); } catch(Exception ex){ ex.printStackTrace(); }}}Copy the code
In addition, Java reflection can retrieve annotation information, which is used a lot in ORM frameworks.
package com.hwdev.demo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @author wangming */ @Retention(retentionPolicy.runtime) @target (elementtype.field) public @interface ORMAnnotation { public String FieldName(); public String FieldType(); }Copy the code
Where @Retention(retentionPolicy.runtime) indicates that annotations can be accessed by reflection at RUNTIME. @target (elementType.field) indicates that this annotation can only be used on fields. Similarly, you can change FIELD to Type or Method, etc.
package com.hwdev.demo; import java.lang.annotation.Annotation; import java.lang.reflect.*; Public ReflectDemo03 {public static void Test() {try {class helloC = Class.forName("com.hwdev.demo.HelloAnnotation"); Field[] fields = helloC.getDeclaredFields(); F. setaccessible (true); for(Field f: fields){// Turn off security checks to improve efficiency. Annotation ann = f.getAnnotation(ORMAnnotation.class); if(ann instanceof ORMAnnotation){ ORMAnnotation ormAnn = (ORMAnnotation) ann; System.out.println("FieldName=" + ormAnn.FieldName()); System.out.println("FieldType=" + ormAnn.FieldType()); } } }catch(ClassNotFoundException | SecurityException ex){ ex.printStackTrace(); } catch(Exception ex){ ex.printStackTrace(); }}}Copy the code
If you execute this example, the following output is displayed:
FieldName=f_author
FieldType=varchar(50)
FieldName=f_ver
FieldType=int
Copy the code
Again, we’ll show you how to use reflection to get the number and type of method parameters, including information about generics:
package com.hwdev.demo; import java.util.ArrayList; import java.util.List; Public class GenericCls {protected List<String> myList = new ArrayList(); public GenericCls(int size){ for(int i = 0; i<size; i++){ myList.add("item"+i); } } public List<String> getList(){ return this.myList; } public String getList(int idx){ return this.myList.get(idx); } } package com.hwdev.demo; import java.lang.reflect.*; Public class ReflectDemo05 {public static void Test() {try {class helloC = Class.forName("com.hwdev.demo.GenericCls"); // Call Object obj = helloc.getconstructor (int.class).newinstance (3); Method method = helloC.getMethod("getList", int.class); Class<? > returnType = method.getReturnType(); System.out.println("ReturnType = " + returnType.getName()); Parameter[] params = method.getParameters(); for(Parameter p : params){ System.out.println("ParameterizedType = " + p.getParameterizedType()); System.out.println("getModifiers = " + p.getModifiers()); System.out.println("getName = " + p.getName()); System.out.println("getType = " + p.getType()); Object ret = method.invoke(obj, new Object[]{2}); System.out.println("ret = " + ret.toString()); Method method2 = helloC.getMethod("getList", null); Type greturnType = method2.getGenericReturnType(); System.out.println("getGenericReturnType = " + returnType.getName()); if(greturnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) greturnType; System.out.println("type = " + type.getTypeName()); Type[] typeArguments = type.getActualTypeArguments(); for(Type typeArgument : typeArguments){ Class typeArgClass = (Class) typeArgument; System.out.println("typeArgClass = " + typeArgClass); } } }catch(ClassNotFoundException | SecurityException ex){ ex.printStackTrace(); } catch(Exception ex){ ex.printStackTrace(); }}}Copy the code
Run the example above, and the output looks like the following.
ReturnType = java.lang.String
ParameterizedType = int
getModifiers = 0
getName = arg0
getType = int
ret = item2
getGenericReturnType = java.lang.String
type = java.util.List<java.lang.String>
typeArgClass = class java.lang.String
Copy the code
There is a lot more to learn about reflection, such as using reflection to dynamically load plug-ins. The efficiency of reflection can be solved by using efficient third-party reflection libraries, or by adding buffering mechanisms, which are not covered here.
Click to follow, the first time to learn about Huawei cloud fresh technology ~