Java learning notes -- Java language foundation (classloader, reflection)

Posted by emcb_php on Wed, 04 Mar 2020 06:16:36 +0100

1, Classloader

Loading overview of class 1.1

Class loading overview
	When a program wants to use a class, if the class has not yet been loaded into memory,
	The system will initialize this class in three steps: loading, connecting and initializing.
	Load 
		It means to read the class file into memory and create a class object for it.
		When any Class is used, the system will create a Class object.
	Connect
		Verify that you have the correct internal structure and are consistent with other classes
		Preparation: responsible for allocating memory for static members of the class and setting default initialization values
		Parsing: converting symbolic references in a class to direct references
  Initialization: This is the initialization step we talked about before

Loading time of class 1.2

  • Create an instance of the class for example: new Student()
  • Access the static variable of the class, or assign a value to the static variable, for example: Math.PI
  • Call the static method of the class for example: Math.abs()
  • Using reflection to force the creation of java.lang.Class objects corresponding to a class or interface
  • Initializing a subclass of a class
  • Directly use java.exe command to run a main class

Classification and function of class 1.3 loaders

1. Overview of classloader
	It is responsible for loading the. Class file into the inner and generating the corresponding class object for it.
2. Classloader classification
	Bootstrap ClassLoader root loader
	Extension ClassLoader
	Sysetm ClassLoader system classloader
 3. Function of classloader
	Bootstrap ClassLoader root loader
		Also known as the bootstrap loader, it is responsible for loading Java core classes
		For example, System,String, etc. In the rt.jar file under the lib directory of JRE in JDK
	Extension ClassLoader
		Responsible for the loading of jar packages in the extension directory of JRE.
		In JDK, under the lib directory of JRE, the ext directory
	Sysetm ClassLoader system classloader
		It is responsible for loading the class file from the java command when the JVM starts, as well as the jar package and classpath specified by the classpath environment variable

Two. Reflection

1. Overview of reflection:
2. there are three ways to get the class file object:

  • getClass() method of Object class
  • Static property class
  • Static method forName() in Class
public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
        Reflect, analyze the composition of this class, call the properties and functions in the class
         */
        //Get the bytecode file object of a class
        //Method in method 1 getClass method object class, object call
        Object o = new Object();
        Class aClass = o.getClass();
        System.out.println(aClass);
        //Mode 2 each class will have a static class attribute
        Class aClass1 = Object.class;
        Class stringClass = String.class;
        System.out.println(aClass==aClass1);
        System.out.println(stringClass);
        //Method 3 uses the method forName parameter in Class to pass the fully qualified name (package name + Class name)
        Class aClass2 = Class.forName("fanshe.Method.Demo01");
        System.out.println(aClass2);
    }
}

Obtain the bytecode file object, and analyze the construction methods, member variables and member methods in the class.

2.1 nonparametric construction method by reflection

Take the Student class as an example

public class Student {
    //Provide construction method
    public Student() {
        System.out.println("Null argument constructor called");
    }

    public Student(String name) {
        System.out.println("The constructor of a parameter calls,Parameter value");
    }

    public Student(String name,int age,char sex) {
        System.out.println("The constructor of three parameters calls");
    }

    private Student(String name,int age) {
        System.out.println("Private construction method of two parameters");
    }
}

Get all construction methods:

Get all construction methods
 Public constructor <? > [] getconstructors() get all construction methods without private
 Public constructor <? > [] getdeclaredconstructors() gets all construction methods including private
 Get a single construction method
 Public constructor < T > getconstructor (class <? >... Parametertypes) get a single constructor without private
 Public constructor < T > getdeclaredconstructor (class <? >... Parametertypes) obtain that a single constructor contains private
public class Test01 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
        Class aClass = Class.forName("num23.Metnod.Student");
        //  1) A construction method to obtain the class: constructor C = bytecode object. Getdeclaredconstructor of the class (parameter 1.class, parameter 2.class);
        //Private construction
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
        //Use the methods in the construction method object to create the class object.
        //Cancel syntax detection of permission
        declaredConstructor.setAccessible(true);
        Student s1 = (Student) declaredConstructor.newInstance("Zhang San", 20);
        System.out.println(s1);
        //Public ownership
        Constructor declaredConstructor1 = aClass.getDeclaredConstructor(String.class, int.class, char.class);
        //It's not private. You don't need to cancel the syntax detection of permission
        Student s2 = (Student) declaredConstructor1.newInstance("Li Si", 23, 'male');
        System.out.println(s2);
    }
}

Note: when we need to take empty parameter construction, we don't need to get empty parameter construction object.

  Class studentClass2 = Class.forName("num23.Metnod.Student");
  Student student2 = (Student) studentClass2.newInstance();
  System.out.println(student2);

2.2 get member variables by reflection

Get all member variables
 public Field[] getFields() gets all member variables that are inherited from the parent class
 public Field[] getDeclaredFields() gets all member variables, including private and inherited member variables from the parent class
 Get a single member variable
public Field getField(String name)
public Field getDeclaredField(String name)

Provides a class. Create several member variables

public class Teacher {
    //Provide member variables
    public String name;
    int age;
    private char sex;
}

Test class:

public class MyTest {
    public static void main(String[] args) throws Exception{
        Class teacherClass = Class.forName("org.westos.demo4.Teacher");
        //getFields() gets all the public fields
        Field[] fields = teacherClass.getFields();
        for (Field field : fields) {
            System.out.println(field.toString());
        }
        //Get all field objects, including private
        Field[] declaredFields = teacherClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //Get the public single field object and pass in the field name
        Field name = teacherClass.getField("name");
        System.out.println(name);
        //Gets a single field object that is not public.
        Field field2 = teacherClass.getDeclaredField("age");
        System.out.println(field2);
        Field field3 = teacherClass.getDeclaredField("sex");
        System.out.println(field3);
    }
}

Assign values to member variables:

public class MyTest2 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, ClassNotFoundException {
        //Gets the bytecode file object of this class.
        Class teacherClass =Class.forName("num23.Method2.Teacher") ;
        //Get name field object
        Field field = teacherClass.getField("name");
        Object obj = teacherClass.newInstance();
        //Call the method in the Field class to assign a value to the Field
        //Parameter 1, an object of this type is required
        //Parameter 2: the specific value of the field
        field.set(obj,"Zhang San");
        //Get the value of the field
        Object o = field.get(obj);
        System.out.println(o);
        //Use reflection to assign value to private field
        //Get private field object
        Field sexFiled = teacherClass.getDeclaredField("sex");
        //Call the set() method in the Field class to assign a value to a private Field
        //For the assignment of private fields, we need to cancel the permission detection
        sexFiled.setAccessible(true);
        sexFiled.set(obj,'male');
        Object o1 = sexFiled.get(obj);
        System.out.println(o1);
    }
}

2.3 member acquisition by reflection

Get all member methods
	public Method[] getMethods() / / get all public member methods without private public methods inherited from the parent class
	public Method[] getDeclaredMethods() / / get all member methods including private
 Get single member method
	//Parameter 1: method name parameter 2: class object of method row parameter
	Public method getmethod (string name, class <? >... Parametertypes) / / get a single method without private
	Public method getdeclaredmethod (string name, class <? >... Parametertypes) / / get a single method including private

Provide a Student class and some member methods

public class Student {
    //Provide method
    public void show1(){
        System.out.println("Empty ginseng show1 Method");
    }
    public void show2(String name,int age){
        System.out.println("Two parameter method");
    }

    public int show3(String name, int age,char sex) {
        System.out.println("Method of three parameters");
        return 100;
    }

    private int test(String name, int age, char sex) {
        System.out.println("Private method");
        return 100;
    }
}

Test class:

public class MyTest {
    public static void main(String[] args) throws Exception {
        //Get the bytecode file object of this class
        Class studentClass= Class.forName("num23.Method3.Student");
        //Get all the public method object arrays, including the public method objects of the inherited parent class
        Method[] methods = studentClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        //Get all method objects, including private methods, excluding method objects of the parent class
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        //Get a single public method object
        //Parameter 1, method name parameter 2: variable parameter, which passes in bytecode type of parameter type
        Method show = studentClass.getMethod("show1");
        System.out.println(show);
        Method show2 = studentClass.getMethod("show2", String.class, int.class);
        System.out.println(show2);
        Method show3 = studentClass.getMethod("show3", String.class, int.class, double.class);
        System.out.println(show3);
        //Get a single private method object
        Method test = studentClass.getDeclaredMethod("test", String.class, int.class, double.class);
        System.out.println(test);
    }
}

Using reflection to call methods

public class MyTest2 {
    public static void main(String[] args) throws Exception {
        //Method execution is called by reflection.
        //Get the bytecode file object of this class
        Class studentClass = Class.forName("num23.Method3.Student");
        //Get method object
        Method showMethod = studentClass.getMethod("show1");
        //Get the class object
        Object obj = studentClass.newInstance();
        //Call the invoke() Method in the Method class, and let show call to execute
        //Parameter 1, object of class, parameter 2, actual value passed to parameter of method
        showMethod.invoke(obj);
        //Call the method execution of two parameters
        Method show2 = studentClass.getMethod("show2", String.class, int.class);
        //Parameter 1, object of class, parameter 2, actual value passed to parameter of method
        show2.invoke(obj, "Zhang San", 23);
        Method show3 = studentClass.getMethod("show3", String.class, int.class, char.class);
        //After the invoke() method is called, the value returned is the value returned by calling the method
        //When the method has a return value
        Integer invoke = (Integer) show3.invoke(obj, "Li Si", 25, 'male');
        System.out.println(invoke);
        //Private method execution is called by reflection.
        Method test = studentClass.getDeclaredMethod("test", String.class, int.class, char.class);
        //Call private method, cancel private permission verification
        test.setAccessible(true);
        //Get return value
        Integer invoke1 = (Integer) test.invoke(obj, "Zhao Liu", 25,  'male');
        System.out.println(invoke1);
    }
}

3, Reflex exercise

(1)

When the ArrayList set specifies that the generics are integers, there is no way for us to add a string in the compiler. Because there is syntax check in the compilation of generics, the compilation time cannot be completed. We can only complete it in the runtime, because generics will be automatically erased after the runtime. To complete this requirement in the runtime, we need to use reflection

public class MyTest2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //An object of ArrayList < integer > to add string data to this collection
        ArrayList<Integer> list = new ArrayList<>();
        list.add(200);
        list.add(200);
        list.add(200);
        //Get bytecode file
        Class listClass = list.getClass();
        //Parameter 1: method name parameter 2: class of method parameter
        Method add = listClass.getDeclaredMethod("add",Object.class);
        //Parameter 1, object of class, parameter 2, actual value passed to parameter of method
        add.invoke(list,"sd");
        System.out.println(list);
    }
}

(2) Write a general setting of a property of an object to a specified value through reflection

Set a Student class:

public class Student {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Set a tool class:

public class MyUtils {
    public static void setProperte(Object obj,String properteName,Object value) throws NoSuchFieldException, IllegalAccessException {
        //Bytecode file 
        Class aClass = obj.getClass();
        //Get member variable (field) according to parameter
        Field declaredFields = aClass.getDeclaredField(properteName);
        //Cancel syntax detection
        declaredFields.setAccessible(true);
        //Sets a value for the specified member variable of the specified object
        declaredFields.set(obj,value);
    }
}

Test class:

public class MyTest {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Student student = new Student();
        //Parameter 1 object
        //Parameter 2 member variable
        //Parameter 3 member variable assignment
        MyUtils.setProperte(student,"name","Zhang San");
        MyUtils.setProperte(student,"age",52);
        System.out.println(student.getName());
        System.out.println(student.getAge());
    }
}

(3) Run profile content by reflection

Setting configuration file: peizhi.properties

className=fanshe.yingyong.Dog
methodName=eat
public class MyTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Properties properties = new Properties();
        //Load profile
        properties.load(new FileReader("src/fanshe/peizhi.properties"));
        //Get bytecode file
        Class aClass = Class.forName(properties.getProperty("className"));
        //Get the object aClass.getDeclaredConstructor() by reflection to get the constructor object
        //newInstance() get object
        Object obj = aClass.getDeclaredConstructor().newInstance();
        //Get method parameter name by reflection
        Method methodName = aClass.getDeclaredMethod(properties.getProperty("methodName"));
        methodName.invoke(obj);
    }
}
class Dog{
    public void eat(){
        System.out.println("Dogs eat meat.");
    }
}
class cat{
    public void eat(int age){
        System.out.println("Cats eat fish."+age);
    }
}
Published 25 original articles, won praise 5, visited 647
Private letter follow

Topics: Java JDK jvm Attribute