Abstract:Java reflection is a very powerful mechanism for detecting the fields, methods, and constructors of internal classes in the same system. Reflectance technologies, such as Hibernate and Spring, are heavily used in many of its Java frameworks. Arguably, the nature of reflection allows Java to build incredibly powerful, flexible systems.

This article is shared from the Huawei cloud community “Java programming can not be known reflection usage summary”, the original author: Jackwangcumt.

Java reflection is a very powerful mechanism for detecting the fields, methods, and constructors of internal classes in the same system. Reflectance technologies, such as Hibernate and Spring, are heavily used in many of its Java frameworks. Arguably, the nature of reflection allows Java to build incredibly powerful, flexible systems.

While Java reflection is inefficient, slow, and insecure, there are many scenarios where these characteristics are not a major factor, or where performance can be progressively improved through caching or JVM optimization.

According to the Web site, reflection is a relatively advanced language feature and a powerful technique for inspecting or modifying the behavior of an application in the JVM at run time. It enables an application to perform operations that would otherwise be impossible.

The following is a summary of the basics of Java reflection:

Start by defining a MyBase class with both private and public fields. There are also public and private methods. Examples of MyBase classes are as follows:

package com.hwdev.demo; Public class myBase {public int version = 1; /** ** @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 method getData(){return this.date; }}

Here we define another Hello class, which inherits from the MyBase class. This class is mainly used to verify the use of reflection on the 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; }}

One of the most powerful things 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 fetch the corresponding Class object by passing in the full path string name, which is very convenient. In addition, through getField method and getMethod method, the specified field and method can be obtained and called dynamically.

package com.hwdev.demo; import java.lang.reflect.*; import java.util.Arrays; Class.forName * @author wangming */ public Class reflectDemo01 {public static void Test() {try {public Class reflectDemo01 {public static void Test() {try { // Class Class helloC = class.forName ("com.hwdev.demo.Hello"); Field [] fields = helloc.getFields (); System.out.println(Arrays.toString(Fields)); Arrays.toString(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 ! = null){// Turn off security checks to improve efficiency f.setAccessible(true); String author = (String) f.set (obj); System.out.println("author=" + author); Method [] Method = helloc.getMethods (); // Author =JackWang} // private Method [] Method = helloc.getMethods (); System.out.println(Arrays.toString(methods)); System.out.println(Arrays.toString(methods)); System.out.println(Arrays.toString(methods)); / / this class all Method [] methods2. = helloC getDeclaredMethods (); Println (Arrays.toString(methods2)); println(Arrays.toString(methods2)); // Say (java.lang.String) Method m = Helloc.getDeclaredMethod (" Say ",String. Class); if (m ! = null){// Turn off security checks to 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(); }}}

The xxx.getMethods() method, by default, returns the public methods of the class, parent class, and parent interface, while the xxx.getDeclaredMethods() method returns all methods of the class, including private methods. Similarly, the other getXXX and getDeclaredXXX are used similarly in the reflection API.

package com.hwdev; import com.hwdev.demo.ReflectDemo01; /** * * @author wangming */ public class Main { /** * @param args the command line arguments */ public static void Class.forName reflectDemo01.test (); Class.forName reflectDemo01.test (); }}

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

Field [] Fields = Helloc. GetFields (); Field [] Fields = Helloc. 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 of the methods of this class, the Hello class, both public and private. As a result, Java reflection can access private fields and methods of a class, exposing internal information, which is why Java reflection is a security issue.

Since Java methods support overloading, there can be multiple methods with the same name, that is, different parameters. Therefore, when calling a method with reflection, you need to specify the parameter type of the method, so that you can specify which method signature you are calling to. Method m = Helloc. GetDeclaredMethod (” Say “,String. Class); Public void com.hwdev.demo.Hello.say(java.lang.string)

In addition to using Class.forName to reflect, you can also obtain the reflection object by:

Hello hello = new Hello();
Class helloC = hello.getClass();
Field [] fields = helloC.getFields();
//////////////////////////////////////////
Class helloC = Hello.class; 
Field [] fields = helloC.getFields();

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.*; Public class reflectDemo02 {public static void Test() {try {/** * public class reflectDemo02 {public static void Test() {try {/** * public class reflectDemo02 {public static void Test() {try {// Class helloC = Hello.class; // Object obj = Helloc.newInstance (); GetDeclaredField (" Company "); if (f ! = null){// private must be enabled f.setAccessible(true); // Set the private field value f.set(obj, "newKZ"); String fv = (String) f.et (obj); System.out.println("company=" + fv); //company=newKZ} // getDeclaredMethod(" GetDeclaredMethod "); 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(); }}}

In addition, Java reflection can retrieve annotation information, which is used a lot by 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(); }

Where, @Retention(RetentionPolicy.Runtime) indicates that an annotation 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, Method, etc.

package com.hwdev.demo; import java.lang.annotation.Annotation; import java.lang.reflect.*; Public class reflectDemo03 {public static void Test() {try {class reflectDemo03 = public class reflectDemo03 {public static void Test() {try {class helloC = Class.forName("com.hwdev.demo.HelloAnnotation"); Field[] fields = helloC.getDeclaredFields(); For (Field f: fields){// turn off safety checks for efficiency f.setAccessible(true); 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(); }}}

Execute this example, and the output is as follows:

FieldName=f_author
FieldType=varchar(50)
FieldName=f_ver
FieldType=int

Third, 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 class genericCls <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"); // 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(); }}}

Execute the above example, and the output looks like this.

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

There is a lot more to be said about reflection, such as using reflection technology to dynamically load plug-ins. The problem of reflection efficiency can be solved by using an efficient third party reflection library, or by adding buffering mechanism, which will not be discussed here.

Click on the attention, the first time to understand Huawei cloud fresh technology ~