Interviewer: what is Java reflection?

  • I concept

  • II common method

  • III Typical examples

  • IV Method class

  • V Reflection of array

  • Vi Conclusion

I concept

Reflection is to map various components of Java into corresponding Java classes.

The construction method of Class is private, which is created by the JVM.

Reflection is a feature of the Java language, which allows programs to check themselves and operate on internal members at run time (not at compile time). For example, it allows a Java class to get all its member variables and methods and display them. This capability of Java may not be used much in practical applications, but it does not exist in other programming languages. For example, in Pascal, C, or C + +, there is no way to obtain information about function definitions in a program. (from Sun)

JavaBean is one of the practical applications of reflection. It allows some tools to visually operate software components. These tools dynamically load and obtain the properties of Java components (classes) through reflection.

Reflection has existed since 1.2. The following three frameworks will use the reflection mechanism, involving the Class "Class". It is impossible to directly new CLass(), whose object is a bytecode in memory

An instance of the Class represents classes and interfaces in a running Java application. Enumeration is a kind and annotation is an interface. Each array belongs to a Class mapped as a Class object, which is shared by all arrays with the same element type and dimension.

The basic Java types (boolean, byte, char, short, int, long, float, and double) and the keyword void are also represented as class objects. Class has no public constructor.

Class objects are automatically constructed by the Java virtual machine when loading classes and by calling the defineClass method in the class loader.

Person p1 = new Person();
//Bytecode can be obtained in the following three ways
CLass c1 = Date.class();
p1.getClass();
//If it exists, load it. Otherwise, create a new one. The third one is often used. The name of the class does not need to be known when writing the source program and is passed back at runtime
Class.forName("java.lang.String");

Class. The forname() bytecode has been loaded into the java virtual machine to get the bytecode; The bytecode has not been generated in the java virtual machine and loaded by the class loader. The loaded bytecode is buffered into the virtual machine.

Consider the following simple example to see how reflection works.

import java.lang.reflect.*;

public class DumpMethods {
   public static void main(String args[]) {
      try {
           Class c = Class.forName("java.util.Stack");

           Method m[] = c.getDeclaredMethods();

           for (int i = 0; i < m.length; i++)
               System.out.println(m[i].toString());
      }
      catch (Throwable e){
            System.err.println(e);
      }
   }
}

public synchronized java.lang.Object java.util.Stack.pop()
public java.lang.Object java.util.Stack.push(java.lang.Object)
public boolean java.util.Stack.empty()
public synchronized java.lang.Object java.util.Stack.peek()
public synchronized int java.util.Stack.search(java.lang.Object)

This lists Java util. The name of each method of the stack class and their qualifiers and return types. This program uses class ForName loads the specified class and then calls getDeclaredMethods to get the list of methods defined in this class. java.lang.reflect.Methods is a class used to describe a single method in a class.

The following example uses the Class object to display the Class name of the object:

void printClassName(Object obj) {
       System.out.println("The class of " + obj +
                     " is " + obj.getClass().getName());
}

You can also use a Class literal (JLS Section 15.8.2) to obtain a Class object of the specified type (or void). For example:

System.out.println("The name of class Foo is: "+Foo.class.getName());

When there are no object instances, there are two main methods.

//Two ways to get class types
Class cls1 = Role.class;
Class cls2 = Class.forName("yui.Role");

Note that in the second method, the parameter in forName must be the complete Class name (package name + Class name), and this method needs to catch exceptions. Now that you get cls1, you can create an instance of Role Class. Using the newInstance method of Class is equivalent to calling the default constructor of the Class.

Object o = cls1.newInstance();
//Create an instance
//Object o1 = new Role();   // Equivalent to the above method

II common method

1. Isprimitive (judge whether it is a basic type of bytecode)

public class TestReflect {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String str = "abc";
        Class cls1 = str.getClass();
        Class cls2 = String.class;
        Class cls3 = null;//null must be added
        try {
            cls3 = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(cls1==cls2);
        System.out.println(cls1==cls3);

        System.out.println(cls1.isPrimitive());
        System.out.println(int.class.isPrimitive());//Determines whether the specified Class object represents a basic type.
        System.out.println(int.class == Integer.class);
        System.out.println(int.class == Integer.TYPE);
        System.out.println(int[].class.isPrimitive());
        System.out.println(int[].class.isArray());
    }
}

result:

true
true
false
true
false
true
false
true

2. Getconstructors and getConstructors()

There is no order of construction methods in java, which is distinguished by type and number of parameters.

public class TestReflect {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException {
        // TODO Auto-generated method stub
        String str = "abc";

        System.out.println(String.class.getConstructor(StringBuffer.class));
    }
}

3. The file class represents a member variable in a class.

import java.lang.reflect.Field;
public class TestReflect {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
        ReflectPointer rp1 = new ReflectPointer(3,4);
        Field fieldx = rp1.getClass().getField("x");//Must be x or y
        System.out.println(fieldx.get(rp1));

        /*
         * private The member variable of must use getDeclaredField and setAccessible(true), otherwise you can't get it
         */
        Field fieldy = rp1.getClass().getDeclaredField("y");
        fieldy.setAccessible(true);//Violent reflex
        System.out.println(fieldy.get(rp1));

    }
}

class ReflectPointer {

    public int x = 0;
    private int y = 0;

    public ReflectPointer(int x,int y) {//alt + shift +s is equivalent to right clicking source
        super();
        // TODO Auto-generated constructor stub
        this.x = x;
        this.y = y;
    }
}

III Typical examples

1. Change b in all String type member variables to a.

import java.lang.reflect.Field;
public class TestReflect {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
        ReflectPointer rp1 = new ReflectPointer(3,4);
        changeBtoA(rp1);
        System.out.println(rp1);

    }

    private static void changeBtoA(Object obj) throws RuntimeException, Exception {
        Field[] fields = obj.getClass().getFields();

        for(Field field : fields) {
            //if(field.getType().equals(String.class))
            //Since there is only one copy of bytecode, the semantics of equals is not accurate
            if(field.getType()==String.class) {
                String oldValue = (String)field.get(obj);
                String newValue = oldValue.replace('b', 'a');
                field.set(obj,newValue);
            }
        }
    }
}

class ReflectPointer {

    private int x = 0;
    public int y = 0;
    public String str1 = "ball";
    public String str2 = "basketball";
    public String str3 = "itcat";

    public ReflectPointer(int x,int y) {//alt + shift +s is equivalent to right clicking source
        super();
        // TODO Auto-generated constructor stub
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "ReflectPointer [str1=" + str1 + ", str2=" + str2 + ", str3="
                + str3 + "]";
    }
}

2. Write a program to call the main method in the class according to the class name provided by the user.

Why use reflection?

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestReflect {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
        String str = args[0];
        /*
         * This will cause the array subscript to be out of bounds, because there is no such character array at all
         * You need to right-click and enter b.Inter (full class name) in run as configurations arguments
         *
         */
        Method m = Class.forName(str).getMethod("main",String[].class);
        //Both of the following methods are OK. The main method requires a parameter

        m.invoke(null, new Object[]{new String[]{"111","222","333"}});
        m.invoke(null, (Object)new String[]{"111","222","333"});//This shows that the array is also an Object
        /*
         * m.invoke(null, new String[]{"111","222","333"})
         * The above can't, because java will unpack automatically
         */
    }
}

class Inter {
    public static void main(String[] args) {
        for(Object obj : args) {
            System.out.println(obj);
        }
    }
}

3. Simulate the instanceof operator

class S {
}

public class IsInstance {
   public static void main(String args[]) {
      try {
           Class cls = Class.forName("S");
           boolean b1 = cls.isInstance(new Integer(37));
           System.out.println(b1);
           boolean b2 = cls.isInstance(new S());
           System.out.println(b2);
      }
      catch (Throwable e) {
           System.err.println(e);
      }
   }
}

In this example, create a Class object of Class s, and then check whether some objects are instances of S. Integer(37) is not, but new S() is.

IV Method class

Represents a method in a class (not an object).

import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
 * Drawing a circle on the blackboard involves three objects. Drawing a circle requires the center and radius of the circle, but it is a private method
 * It is not appropriate to assign to others.
 *
 * When the driver steps on the brake, the driver just gives instructions to the train, and the braking action still needs to be completed by the train.
 *
 * Interviews often test object-oriented design, such as people close the door and people just push the door.
 *
 * This is the expert model: whoever owns the data is an expert, and the method is assigned to who
 */
public class TestReflect {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
        String str = "shfsfs";
        //The package starts with com, which means it is used internally by sun, and the user's package starts with java
        Method mtCharAt = String.class.getMethod("charAt", int.class);
        Object ch = mtCharAt.invoke(str,1);//If the first parameter is null, it must be a static method
        System.out.println(ch);

        System.out.println(mtCharAt.invoke(str, new Object[]{2}));//1.4 syntax

    }

}

V Reflection of array

The Array utility class is used to complete the reflection operation of the Array.

The same type and latitude have the same bytecode.

Int.class and integer Class is not the same bytecode, integer Type, type represents the bytecode int.class = = integer of the basic class corresponding to the wrapper class TYPE.

import java.util.Arrays;

/*
 * From this example, we can see that even if the bytecode is the same, the objects are not necessarily the same, which is not the same thing at all
 *
 */
public class TestReflect {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
        int[] a = new int[3];
        int[] b = new int[]{4,5,5};//The length cannot be specified after direct assignment, otherwise CE
        int[][] c = new int[3][2];
        String[] d = new String[]{"jjj","kkkk"};
        System.out.println(a==b);//false
        System.out.println(a.getClass()==b.getClass());//true
        //System.out.println(a.getClass()==d.getClass());    // There is no comparison between bytecode A and cd
        System.out.println(a.getClass());//Output class [I]
        System.out.println(a.getClass().getName());//Output [I, brackets for array, I for integer

        System.out.println(a.getClass().getSuperclass());//Output class java lang.Object
        System.out.println(d.getClass().getSuperclass());//Output class java lang.Object

        //Since the parent classes are all objects, the following are all possible
        Object obj1 = a;//No, it's Object []
        Object obj2 = b;
        Object[] obj3 = c;//A one bit array of basic types can only be regarded as Object, and it can also be regarded as Object []
        Object obj4 = d;

        //Notice the difference between asList handling int [] and String []
        System.out.println(Arrays.asList(b));//1.4 there are no variable parameters, but arrays are used[[ I@1bc4459 ]
        System.out.println(Arrays.asList(d));//[jjj, kkkk]

    }
}

Vi Conclusion

The above is the simple use of the reflection mechanism. Obviously, friends who have studied spring must understand why we can get the specified methods and variables through the configuration file. When we create objects, we pass in string s, just like what you need, we produce for you, and we have been using objects, This shows that the dynamic characteristics and dependency of java language are greatly reduced.

Keywords: Java Back-end

Added by chalbing on Wed, 26 Jan 2022 20:44:02 +0200