当前位置:网站首页>Reflection - learning notes

Reflection - learning notes

2022-06-25 15:27:00 BlackPenguin

Reflection , Refer to Reverse discovery , Reverse the way to learn and use the inner details of classes . stay Java Runtime , Get the information of the object dynamically , And call its properties .

Get the content of the class dynamically 、 A mechanism for dynamically invoking methods and properties of objects , It's called Java The reflection mechanism of .



Class object 、 Acquisition of class information 、 Class properties and methods

Class object , namely This object refers to a class , Through this object, you can obtain the specific information of the reference class and the attribute methods , Such as class name 、 Package name 、 loader 、 Methods in classes, etc .


One 、 Get class object

Here are four ways to get class objects .

public class MainTest {
    
    public static void main(String[] args) throws Exception {
    
    
        Class<User> userClass = User.class;
        
        Class<?> userClass = Class.forName("reflect.User");	//  Package name in parentheses . Class name 
        
        Class<? extends User> userClass = new User().getClass();
        
        Class<?> userClass = MainTest.class.getClassLoader().loadClass("reflect.User");
    }
}

Two 、 Get class information through class objects

Class<User> userClass = User.class;	//  Class object 

//  Get the name of the class  reflect.User
userClass.getName();
//  Get package name  package reflect
userClass.getPackage();
//  Class loader  [email protected]
userClass.getClassLoader();
//  Parent class  class java.lang.Object
userClass.getSuperclass();
//  Get all interfaces implemented by the class 
userClass.getInterfaces();

Class modifier , Refers to the modifier in front of the class ,public, private, final, abstract Wait is the modifier , Each modifier occupies a bit in the binary .public yes 1,private yes 0;abstract yes 1024…

getModifiers() Get class modifiers , The sum of the modifiers before the class .

//  Class modifier 
userClass.getModifiers();

3、 ... and 、 Get properties in class 、 Modify attribute values

  1. Get the properties of the class

    getFields() obtain Class and its parent class Inside public attribute

    getDeclaredFields() Get all the properties of the current class

    public class Person {
          
        public String firstVar;
        private int secondVar;
        public static double thirdVar;
    }
    
    public class User extends Person{
          
    
        public String name;
        private int age;
        public static String address;
    
        public void method1 () {
          
            System.out.println("method1");
        }
    }
    
    public class MainTest {
          
        public static void main(String[] args) throws Exception {
          
            Class<User> userClass = User.class;
            User user = userClass.newInstance();
    
            Field[] fields = userClass.getFields();	//  Get the properties of the class 
            for(Field f : fields) {
          
                System.out.println(f.getModifiers() + " " + f.getName());
            }
            /* 1 name 9 address 1 firstVar 9 thirdVar */
    
            System.out.println("------------------");
    
            fields = userClass.getDeclaredFields();
            for(Field f : fields) {
          
                System.out.println(f.getModifiers() + " " + f.getName());
            }
            /* 1 name 2 age 9 address */
        }
    }
    

    getFields(): Get class 、 Public attributes in the parent class
    getDeclaredFields(): Get all the properties in the current class ( Including public ownership 、 private )


  2. To pass reflection modify Class Private property when , You must add ageField.setAccessible(true); This sentence , Means that the attribute can be reached .

    Field ageField = userClass.getDeclaredField("age");
    ageField.setAccessible(true);
    ageField.set(user, 40);
    System.out.println(user.getAge());
    

  1. Modify the class Static attribute
    Modify static attributes in the class through reflection , Use addressField.set(null, " The location is ");, Because it is a static property , So use null object , No instantiation object specified .

    Field addressField = userClass.getDeclaredField("address");
    addressField.set(null, " The location is ");
    System.out.println(User.address);
    



Four 、 Get methods in class

  1. Get methods in class

    public class Person {
          
    
        public void func1() {
          
            System.out.println("func1");
        }
    
        private void func2() {
          
            System.out.println("func2");
        }
    }
    
    public class User extends Person {
          
    
        public void method1() {
          
            System.out.println("method1");
        }
    
        private void method2() {
          
            System.out.println("method2");
        }
    
        public static void staticMethod(String msg) {
          
            System.out.println("msg: " + msg);
        }
    }
    
    public class MainTest {
          
        public static void main(String[] args) throws Exception {
          
            Class<User> userClass = User.class;
            User user = userClass.newInstance();
    
            Method[] methods = userClass.getMethods();
            for (Method m : methods) {
          
                System.out.println(m.getModifiers() + " " + m.getName());
            }
            /* 9 staticMethod 1 method1 1 func1 17 wait 17 wait 273 wait 1 equals 1 toString 257 hashCode 273 getClass 273 notify 273 notifyAll */
            
            Method[] declaredMethods = userClass.getDeclaredMethods();
            for (Method m : declaredMethods) {
          
                System.out.println(m.getModifiers() + " " + m.getName());
            }
            /* 2 method2 9 staticMethod 1 method1 */
        }
    }
    

    getMethods(): Get class 、 In the parent class Public methods
    getDeclaredMethods(): Get all methods in the current class


  1. Call... In the class through reflection Private method
    Call private use method.invoke(instance), And need to add method2Method.setAccessible(true);

    Method method2Method = userClass.getDeclaredMethod("method2");
    method2Method.setAccessible(true);
    method2Method.invoke(user);
    

  1. Call... In the class through reflection Static methods
    invoke The object of is null
    Method staticMethod = userClass.getDeclaredMethod("staticMethod", String.class);
    staticMethod.invoke(null, "msg yes ");
    



5、 ... and 、 Get the constructor

  1. Get the constructor

    public class User extends Person {
          
    
        private String address;
    
        public User() {
          
            System.out.println(" Parameterless constructors ");
        }
    
        public User(String address) {
          
            this.address = address;
            System.out.println(" There are reference constructors  " + this.address);
        }
    }
    //……
    // The main function :
    	Constructor<?>[] constructors = userClass.getConstructors();
    	for (Constructor c : constructors) {
          
    	    System.out.println(c.getModifiers() + " " + c.getName());
    	}
    	
    	Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
    	for (Constructor c : declaredConstructors) {
          
    	    System.out.println(c.getModifiers() + " " + c.getName());
    	}
    
  2. Create instances by reflection
    The first one is :User user = userClass.newInstance(); It's usually a parameterless constructor
    The second kind :

    Constructor<User> declaredConstructor= userClass.getDeclaredConstructor();
    declaredConstructor.newInstance();
    
    Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class);
    declaredConstructor1.newInstance(" The address is ");
    

Advantages and disadvantages of reflection

advantage

  1. More flexible procedures , Because reflection is The runtime dynamically gets , It can avoid the inherent logic being written in the program
  2. Make the code more concise , Improve program reusability

shortcoming

  1. Compared with direct call, it has greater performance damage . Because reflection calls native Local method ; And every time newInstance Methods will do security checks , More time-consuming
  2. Internal exposure , There are security risks

For example, we can get the corresponding class instance by passing in a parameter . You can pass in "Basketball","Football" Get the corresponding class , To get the class Basketball、Football Two different instances of . If there are many possible parameters , So using the first method requires many if Judgment statement , Make the code redundant and complex , inflexible . The second method uses the idea of reflection , Get the corresponding class through parameters , And get an instance of this class . So the second method is more flexible , Avoid the inherent logic .

public class BallMainTest {
    

    public static Ball getInstanceByKey(String key) {
    
        if ("Basketball".equals(key)) {
    
            return new Basketball();
        }
        if ("Football".equals(key)) {
    
            return new Football();
        }
        return null;
    }

    public static Ball getInstanceReflectByKey(String key) {
    
        String ballPackage = "reflect";
        Ball ball = null;

        try {
    
        	//  Get class by class name 
            Class<?> ballClass = Class.forName(ballPackage + "." + key);
            //  Get an instance of this class 
            ball = (Ball) ballClass.newInstance();
        } catch (Exception e) {
    
            e.printStackTrace();
        }
        return ball;

    }

    public static void main(String[] args) {
    
        System.out.println(getInstanceByKey("Basketball"));
        System.out.println(getInstanceReflectByKey("Basketball"));
    }
}
原网站

版权声明
本文为[BlackPenguin]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202200502589533.html