反射

Reflect

Java反射机制时在运行状态中,对于任意一个类,都能知道这个类所有的属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为Java语言的反射机制。(就是通过class文件对象,使用该文件中的成员变量、构造方法、成员方法)

获取class文件对象(Class)

  • Object类中的getClass()方法
  • 数据类型的静态属性class
  • Class.forName("类路径")
public class Student {
    private String name;
    Integer age;
    public String addr;

    public Student() {
    }

    public Student(String name, Integer age, String addr) {
        this.name = name;
        this.age = age;
        this.addr = addr;
    }

    private Student(String addr) {
        this.addr = addr;
    }

    public String method(String s) {
        return String.format("method_%s", s);
    }
  
  void show() {
        System.out.println("student show");
    }

    private void test() {
        System.out.println("student test ");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", addr='" + addr + '\'' +
                '}';
    }
}
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // Object类中的getClass()方法
        Student student = new Student();
        Class aClass = student.getClass();

        // 数据类型的静态属性class
        Class bClass = Student.class;

        // Class.forName("类路径")
        Class cClass = Class.forName("com.net.reflect.Student");


        // 三种方式获取的是同一个class文件对象
        // true
        System.out.println(aClass == bClass);
        // true
        System.out.println(bClass == cClass);
    }
}

获取构造方法并使用

public class ReflectDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取字节码文件对象
        Class studentClass = Student.class;

        // 获取所有公共构造方法
        Constructor[] constructors = studentClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        // 获取所有构造方法
        Constructor[] declaredConstructors = studentClass.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        // 获取指定构造方法并使用
        Constructor declaredConstructor = studentClass.getDeclaredConstructor(String.class, Integer.class, String.class);
        System.out.println(declaredConstructor);
        // 创建实例
        Student student = declaredConstructor.newInstance("zhansan", 11, "aaa");
        System.out.println(student);

        // 获取私有方法并使用
        Constructor con = studentClass.getDeclaredConstructor(String.class);
        // 设置访问权限
        con.setAccessible(true);
        // 创建实例
        Student student1 = con.newInstance("bbb");
        System.out.println(student1);
    }
}

获取成员变量并使用

public class ReflectField {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取字节码文件对象
        Class studentClass = Student.class;

        // 获取所有公开的成员变量
        // public java.lang.String com.net.mybatisplus.reflect.Student.addr
        Field[] fields = studentClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        // 获取所有成员变量
        // private java.lang.String com.net.mybatisplus.reflect.Student.name
        // java.lang.Integer com.net.mybatisplus.reflect.Student.age
        // public java.lang.String com.net.mybatisplus.reflect.Student.addr
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        // 获取单个公开成员变量并对其赋值
        Constructor constructor = studentClass.getConstructor();
        Student student = constructor.newInstance();

        Field addr = studentClass.getField("addr");
        addr.set(student, "ccc");
        // Student{name='null', age=null, addr='ccc'}
        System.out.println(student);

        // 获取单个私有成员变量并对其赋值
        Field name = studentClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(student, "zhangsan");
        // Student{name='zhangsan', age=null, addr='ccc'}
        System.out.println(student);

    }
}

获取成员方法并使用

public class ReflectMethod {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取字节码文件对象
        Class studentClass = Student.class;

        // 获取所有公开方法(包括父类)
        Method[] methods = studentClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("-----------------");

        // 获取所有方法(不包括父类)
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("-----------------");

        // 获取单个公开方法并使用
        Constructor constructor = studentClass.getConstructor();
        Student student = constructor.newInstance();

        Method method = studentClass.getMethod("method", String.class);
        Object stuMethod = method.invoke(student, "stuMethod");
        System.out.println(stuMethod);
        System.out.println("-----------------");
        
        // 获取单个私有方法并使用
        Method test = studentClass.getDeclaredMethod("test");
        test.setAccessible(true);
        test.invoke(student);
    }
}

工具类

public class ReflectTool {
    // 赋值对象的任意属性
    public static void setProperty(Object obj, String propertyName, Object value)
            throws NoSuchFieldException, IllegalAccessException {
        
        // 获取字节码文件对象
        Class aClass = obj.getClass();

        // 获取成员变量
        Field declaredField = aClass.getDeclaredField(propertyName);

        // 取消访问检查
        declaredField.setAccessible(true);

        // 赋值
        declaredField.set(obj, value);
    }
}

反射越过泛型检查

public class ListReflect {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List list = Lists.newArrayList();
        Class aClass = list.getClass();

        Method add = aClass.getDeclaredMethod("add", Object.class);

        add.setAccessible(true);
        add.invoke(list, "list1");
        add.invoke(list, 11);
        add.invoke(list, true);

        System.out.println(list);
    }
}

你可能感兴趣的:(反射)