反射:反向调用分离业务

    科技2022-08-17  111

    如果我们想要使用Person类,除了可以用new Person直接对其进行使用外,还可以不通过new直接使用其中所有的内容:

    1、从所有构造方法中直接拿到它的构造方法,包括私有

    注意:所有的类必须有私有构造

    第一种:直接调用无参构造

    Class<?> clazz = Class.forName("com.doit.reflect.Person"); //直接调用默认构造方法 Person p = (Person)clazz.newInstance(); p.setName("徐睿"); p.setAge(20); p.setGender(false); p.setId("1001a"); System.out.println(p);

    第二种:调用指定个数参数或类型的构造

    //对比调用无参与批定参数构造 Constructor<?> c = clazz.getConstructor(); //根据不同的传入参数,传入相应的类型实现调用 Constructor<?> c2 = clazz.getConstructor(String.class, String.class, boolean.class, int.class); Object o = c.newInstance(); Object lss = c2.newInstance("1003b", "lss", false, 33); Object zs = c2.newInstance("1002a", "张三", true, 32); Person p2 = (Person)lss; p2.tell(); System.out.println(zs); System.out.println(lss); System.out.println(o);

    第三种:拿到私有的构造器

    核心代码就在于:先通过getDeclaredConstructor或getDeclaredMethod拿到含私有的构造器或方法,再利用setAccessible进行暴力调用:对象.setAccessible(true)实现暴力反射

    Constructor c2 = clazz.getDeclaredConstructor(int.class); c2.setAccessible(true); Person o = (Person)c2.newInstance(33); System.out.println(o);

    2、从所有的方法中,拿到指定的成员方法

    Person p3 = (Person)clazz.newInstance(); //拿到无参方法tell Method tell = clazz.getMethod("tell"); //拿到一个string参数的方法 Method tell1 = clazz.getMethod("tell", String.class); //调用tell tell.invoke(p3); //调用tell(String name) tell1.invoke(p3, "徐睿");

    3、泛型擦除:去除泛型中的类型限制

    绕过泛型检查,直接在编译后进行擦除,再次证明反射是在编译后才开始生效

    在List<String>中插入任意类型数据:此程序没有任何意义,只是作为一个了解

    public class GenericDemo { static List<String> list = new ArrayList<>(); public static void main(String[] args) throws Exception{ list.add("张三"); //方式1:直接用变量的getclass Class<?> clazz = list.getClass(); //方式2 :直接用包名 Class<?> aClass = Class.forName("java.util.ArrayList"); //拿到增加方法,扩大到object Method ar2 = aClass.getMethod("add", Object.class); ar2.invoke(list, 457); ar2.invoke(list, 984f); Method add = clazz.getMethod("add", Object.class); add.invoke(list,23 ); add.invoke(list, 36.3d); for (Object s : list) { System.out.println(s + "-->" + s.getClass().getTypeName()); } } }

     


    测试的Person类:

    package com.doit.reflect; public class Person { private String id; private String name; private boolean gender; private int age; private Person(int age){ this.age = age; System.out.println(age); } public void tell(){ System.out.println(this.name + "对你说:Hello"); } public void tell(String name){ System.out.println(name + "对你说:你好呀!"); } @Override public String toString() { return "Person{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", gender=" + gender + ", age=" + age + '}'; } public Person() { } public Person(String id, String name, boolean gender, int age) { this.id = id; this.name = name; this.gender = gender; this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isGender() { return gender; } public void setGender(boolean gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
    Processed: 0.037, SQL: 9