Java: reflection mechanism study notes

First, reflection

1 Overview

Reflection: the various components of the package into the category of other objects in the operating state, can be dynamically obtain class information and call the class object's method.

2, advantages and disadvantages

  • advantage
    • It may be the program is running, the operation part of the class.
    • Decoupling can improve the scalability of the program.
  • Shortcoming
    • Produce a series of operations explained, poor performance.

3, the class loading procedure

java language has "a compilation, run anywhere" characteristics of the fine, able to adapt to different platforms, the process is as follows:

  • We javaccommand .javafile is compiled, it will generate on the disk platform that does not face the bytecode files .class.
  • After the class loader through a series of operations, such as loading, and the connection initialization, the .classfile is loaded into memory.
  • Static storage structure .class file represents bytecode runtime data structures into the method area.
  • Then the class loader will be created when a memory java.lang.Classobject, the object contains information such as access data from a variety of areas as a method of programming interface.

Second, get the Class object of three ways

The Class object contains all the information category, that is, we get the Class object class, you can access the JVM in this class. So, how to get it? There are three main ways.

1、Class.forName("全类名")

By Class的静态方法forName("全类名"), Class object and returns the corresponding full class name of the class.

    //Class.forName("全类名");
    Class cls1 = Class.forName("com.my.base.Person");
    System.out.println(cls1);
  • Used for the configuration file, the class name is defined in the configuration file, you can read files dynamically load classes.
  • Full class name refers to: the full package name class name, if found, will throw ClassNotFoundException exception.

2, the class name .class

By 类名的class属性obtaining, returns the object corresponding to the class Class.

    //类名.class;
    Class cls2 = Person.class;
    System.out.println(cls2);
  • The way the program is compiled stage to check whether there is a need to access the Class object, relatively more secure.
  • The way without having to call a method, program performance is relatively good.

3, the object .getClass ()

getClass()The method defined in Object, which returns the object's class to obtain the corresponding Class object.

    //对象.getClass();
    Person p = new Person();
    Class cls3 = p.getClass();
    System.out.println(cls3);

The same byte code file .classin the course of a program is running, it will only be loaded once, regardless of which way acquired by Class objects are the same.

    // == 比较三个对象,都是true

    System.out.println(cls1 == cls2);
    System.out.println(cls1 == cls3);
    System.out.println(cls3 == cls2);

Third, the reflection correlation method

Class object contains information of all classes, which are encapsulated within java.lang.reflectthe package, has become one of the class, incomplete follows:

Method Field Annotation Constructor Package Modifier Parameter
Method in class Field class Class Notes The class constructor Bags Modifiers class Method parameter class

Class in the appropriate class provides methods to obtain this information, due to the numerous methods, specific JDK also need to see official documents.

Here I summarize a few general:

  • Call the corresponding getXxxusually obtain public information corresponding to a single modification, getDeclaredXxxis not considered modifiers, can not be found, the superclass to find.

  • Call the corresponding getXxxsusually get an array of public information corresponding modification, getDeclaredXxxsmodifier is not considered, can not be found, the superclass to find.

  • The above parameters encountered two different situations, if the method itself is used to obtain public information modified forced to get permission to fail, it will throw an exception:
    • For Field, the brackets are: "参数名".
    • For Method, in parentheses: "方法名",参数类型对应的类.
    • For Constructor, in parentheses: "参数对应的类".
  • Field class has a method to get the value of: Object get(Object obj), there is provided a method values: void set(Object obj, Object value).
  • Method class can invoke methods: Object invoke(Object obj, Object... args).
  • Constructor class creates instances: T newInstance(Object... initargs)if no-argument constructor class, can be used directly in class Class newInstance () method creates an instance.

  • In reflection, nothing is private, if there is, then the use of xxx.setAccessible(true)brute force.
  • Modifier is determined, getModifiers()when the value of the return int is the modifier indicating the number of the individual and can be determined by bit operation, (xx.getModifiers()&Modifier.STATIC)!=0indicating the presence of the static modifier.

ps: there must be missing API, to use the time when, looking through the API gets the job done.

Four, Demo × 2

1, try to write a clone () method

package com.my.reflect.practice;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * @auther Summerday
 */

@SuppressWarnings("unchecked")
public class ImplementClone {
    public Object clone(Object o) throws Exception{
        //获取对象的实际类型
        Class<Object> clz = (Class<Object>) o.getClass();

        //获取所有构造方法
        Constructor<Object>[] cs = (Constructor<Object>[]) clz.getDeclaredConstructors();
        //任取一个构造方法
        Constructor<Object> c = cs[0];

        //防止取出构造方法为私有
        c.setAccessible(true);

        //该构造方法参数有or无?

        //获取参数类型
        Class[] ps = c.getParameterTypes();
        //存储参数的数组
        Object[] os = new Object[ps.length];

        for(int i = 0;i<ps.length;i++){
            //判断是否为基本类型
            if(ps[i].isPrimitive()){
                if(ps[i] == boolean.class)
                    os[i] = false;
                else if(ps[i] == char.class)
                    os[i] = '\u0000';
                else
                    os[i] = 0;
            }else{
                os[i] = null;
            }
        }
        //执行构造方法创建对象
        Object obj = c.newInstance(os);

        //获取属性数组
        Field[] fs = clz.getDeclaredFields();

        for (Field f : fs){

            //如果final修饰则返回,无法修改
            if((f.getModifiers()&Modifier.FINAL)!=0){
                continue;
            }
            //暴力破解
            f.setAccessible(true);

            //取出原属性值
            Object value = f.get(o);

            //将取出的属性值赋值给新对象的属性
            f.set(obj, value);
            
        }
        return obj;
    }
}

2, using the configuration file dynamic loading

package com.my.reflect.practice;

/**
 * @auther Summerday
 */

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 *
 *     参考黑马程序员教学视频
 *
 * 实现:1、配置文件  2、反射
 *
 * 一、将需要创建的对象的全类名和需要执行的方法定义在配置文件中
 *
 * 二、在程序中加载读取配置文件
 *
 * 三、使用反射来加载类文件进内存
 *
 * 四、创建对象
 *
 * 五、执行方法
 *
 */
public class ReflectTest {

    public static void main(String[] args) throws Exception {

        //1、加载配置文件

        //1.1 创建Properties对象
        Properties pro = new Properties();

        //1.2 加载配置文件,转换为一个集合

        //1.2.1获取class目录下的配置文件

        //创建类加载器
        ClassLoader classLoader = ReflectTest.class.getClassLoader();

        InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
        pro.load(resourceAsStream);

        //2、获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3、加载该类进内存
        Class cls = Class.forName(className);

        //4、创建对象
        Object obj = cls.newInstance();

        //5、获取方法
        Method method = cls.getMethod(methodName);

        //6、执行方法
        method.invoke(obj);

    }
}

It will have more and more need to use real scenarios reflecting the soul of technology, in short, a good look, a good school.

Guess you like

Origin www.cnblogs.com/summerday152/p/12333912.html