反射

1. 什么是反射

动态语言 : 在运行时代码可以根据某些条件改变自身结构

java正是因为有了反射 , 才可以称为"准动态语言"

2.反射相关的主要API

3.Class类

3.1 Class类的理解

3.2 获取Class实例的四种方式

3.3 Class实例可以是哪些结构 ?

4. 代码

//使用反射创建对象
    @Test
    public void test2()throws Exception{
        Class clazz = Person.class;
        //1.通过反射创建person
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        Object arthur = constructor.newInstance("Arthur",24);
        Person person = (Person) arthur;
        System.out.println(person);
        //2.调用属性
        Field age = clazz.getDeclaredField("age");
        age.set(person,25);
        System.out.println(person);
        //3.调用方法
        Method show = clazz.getDeclaredMethod("show");
        String str = (String) show.invoke(person);
        System.out.println(str);

        //通过反射调用私有的结构 : 构造器 , 属性, 方法
        //构造器
        Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
        constructor1.setAccessible(true);
        Person tom = (Person) constructor1.newInstance("Tom");
        System.out.println(tom);
         //属性
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(tom,"Arthur");
        System.out.println(tom);
        //方法
        Method showNation = clazz.getDeclaredMethod("showNation", String.class);
        showNation.setAccessible(true);
        String str1 = (String) showNation.invoke(tom,"China");
        System.out.println(str1);
    }

    //反射的动态性
    @Test
    public void test3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        int i = new Random().nextInt(3);
        String path = "";
        switch(i){
            case 0:
                path = "java.lang.Object";
                break;
            case 1:
                path = "java.util.Date";
                break;
            case 2:
                path = "com.atguigu.java.Reflection.Person";
                break;
        }
        Object instance = getInstance(path);
        System.out.println(instance);
    }
    public Object getInstance(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class clazz = Class.forName(path);
        return clazz.newInstance();
    }
public class ReflectionTest2 {
    //调用运行时类 指定的属性
    @Test
    public void test1() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class<Person> clazz = Person.class;
        //1.创建运行时类的对象
        Person person = clazz.newInstance();
        //2.获取要操作的属性
        Field name = clazz.getDeclaredField("name");
        //3.保证当前属性是可访问的
        name.setAccessible(true);
        //4.通过属性 , 设置指定对象的值
        name.set(person,"Tom"); //value1 : 要设置的对象 , value2:设置的值
        System.out.println(person);
    }

    //调用运行时类方法
    @Test
    public void test2() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class clazz = Person.class;
        //1.创建对象
        Object person = clazz.newInstance();
        //2.获取调用的方法
        //value1: 方法名称 , value2:方法的形参类型
        Method show = clazz.getDeclaredMethod("showNation",String.class);
        //3.声明
        show.setAccessible(true);
        //4.通过方法调对象 , 来调用此方法
        //invoke()的返回值 即为被调用方法的返回值
        Object china = show.invoke(person, "China");
        System.out.println(china);
        System.out.println("************************调用静态方法****************************");
        Method showDance = clazz.getDeclaredMethod("showDance");
        showDance.setAccessible(true);
        //静态方法 , 直接传入当前对象
        //没有返回值就为null
        Object dance = showDance.invoke(Person.class);
        //Object dance = showDance.invoke(null); 也可
        System.out.println(dance);
    }

    //调用运行时类的构造器
    @Test
    public void test3() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Person.class;
        Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
        constructor.setAccessible(true);
        Object tom = constructor.newInstance("Tom",29);
        System.out.println(tom);
    }
}
public class Person{
   private String name;
    public int age;

    public Person() {
    }

    private Person(String name) {
        this.name = name;
    }

    public Person(int age) {
        this.age = age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private String getName() {
        return name;
    }

    private void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String show(){
      return "I'm Chinese";
    }

    private String showNation(String nation){
        System.out.println("My nationality is "+nation);
        return nation;
    }

    private static void showDance(){
        System.out.println("dancing with your ghost ");
    }
}

4.1 利用发射读取配置文件

4.2 反射获取运行时类父类的泛型

5. 总结

从代码角度来说 : 没有反射以前 , 只能通过new 来创建对象 , 调用属性和方法 , 有了反射以后 , 可通过API动态的创建对象及调用属性和方法(不用写死了).

从逻辑角度来说 : 万物皆对象 , 类本身也是对象 ! 

posted @ 2021-03-03 16:21  Anonymity_Zhang  阅读(36)  评论(0编辑  收藏  举报