反射的使用

用到的类和文件

在这里插入图片描述

前期准备

创建一个Person对象

public class Person {
    //私有成员变量
    private String name;
    //成员变量
    int age;
    //公共成员变量
    public String address;
    //多参构造器
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //私有带参构造器
    private Person(String name) {
        this.name = name;
    }
    //公共无参构造器
    public Person() {
    }
    //公共多参构造器
    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    //公共方法
    public void show() {
        System.out.println("show");
    }
    //公共带参方法
    public void method(String s) {
        System.out.println("method " + s);
    }
    //公共带参带返回值方法
    public String getString(String s, int i) {
        return s + "-->" + i;
    }
    //私有无参方法
    private void function() {
        System.out.println("function");
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address
                + "]";
    }
}

常用的反射方法

public class Main {
    //获得Class对象
    public static void getclass() throws Exception {
        //1.通过对象调用 getClass() 方法来获取
        Person person = new Person();
        Class<? extends Person> class1 = person.getClass();
        //2.通过 类名.class 的方式得到
        //  该方法最为安全可靠,程序性能更高
        //  说明所有类中都有隐藏变量class
        Class<Person> class2 = Person.class;
        //3.通过 Class 对象的 forName() 静态方法来获取
        //  用的最多,会抛异常
        Class<?> class3 = Class.forName("com.Person");
        //一个类在jvm中只会有一个class实例,所以下面结果都为true
        System.out.println(class1.equals(class2));
        System.out.println(class2.equals(class3));
    }
    // 获取类的所有构造方法
    public static void getAllConstruct() throws Exception{
        Class<?> aClass = Class.forName("com.Person");
        //获得类的所有构造方法的列表
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.toString());
        }
    }
    //获取无参构造方法
    public static void getConstruct1() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取class对象
        Class<?> aClass = Class.forName("com.Person");
        //2.获取无参构造方法
        Constructor<?> class_construct = aClass.getDeclaredConstructor();
        //3.利用无参构造生成对象
        Object o = class_construct.newInstance();
        //3.1如果只需要利用无参构造来创建实例
        //   那么也可以不用获取构造器
        //   直接使用newInstance方法
        Object o1 = aClass.newInstance();
        System.out.println(o);
        System.out.println(o1);
    }
    //获取带参构造方法
    public static void getConstruct2() throws Exception{
        Class<?> aClass = Class.forName("com.Person");
        //com.Person类中需要有一个(String name, int age, String address)的构造器
        Constructor<?> declaredMethod = aClass.getDeclaredConstructor(String.class, int.class,String.class);
        Object o = declaredMethod.newInstance("名字", 24,"地址");
        System.out.println(o);
    }
    //获取private修饰的构造方法
    public static void getConstruct3() throws Exception{
        Class<?> aClass = Class.forName("com.Person");
        Constructor con = aClass.getDeclaredConstructor(String.class);
        //给与访问权限
        con.setAccessible(true);
        Object o = con.newInstance("私有带参构造器被创建");
        System.out.println(o);
    }
    //给成员变量赋值
    public static void setData() throws Exception {
        Class<?> aClass = Class.forName("com.Person");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        Object o = declaredConstructor.newInstance();
        System.out.println(o);
        //根据参数名设置值
        Field name = aClass.getDeclaredField("name");
        //给与权限
        name.setAccessible(true);
        //设置参数值
        name.set(o,"名字");
        System.out.println(o);
    }
    //获取成员变量
    public static void getData() throws Exception{
        Class<?> aClass = Class.forName("com.Person");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        Object o = declaredConstructor.newInstance();
        //根据参数名生成字段"对象",此处的name字段是私有的
        Field name = aClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o,"名字");
        //通过字段"对象"的get方法获取字段值,参数是字段所在的对象
        System.out.println(name.get(o));
    }
    //获取无参无返回值成员方法
    public static void getMethod1() throws Exception{
        /**
         * 1、public 方法 getMethod(String name, Class<?>... parameterTypes):获取所有方法,包括父类的
         * 参数 :	name:方法的名称  parameterTypes:该方法的参数列表
         * 2、public 方法 getDeclaredMethod(String name, Class<?>... parameterTypes):获取所有子类定义的方法
         * 参数 :	name:方法的名称  parameterTypes:该方法的参数列表
         */
        Class<?> aClass = Class.forName("com.Person");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        Object o = declaredConstructor.newInstance();
        //获取需要的方法对象
        Method show = aClass.getDeclaredMethod("show");
        /**
         * public Object invoke(Object obj, Object... args)
         * obj - 被调用的对象  args - 用于方法调用的参数
         */
        show.invoke(o);
    }
    //获取获取有参有返回值成员方法,并调用
    public static void getMethod2() throws Exception{
        Class<?> aClass = Class.forName("com.Person");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        Object o = declaredConstructor.newInstance();
        //获取带参无返回值方法
        Method method = aClass.getDeclaredMethod("method", String.class);
        method.invoke(o,"带参无返回值");
        //获取带参带返回值方法
        Method getString = aClass.getDeclaredMethod("getString", String.class, int.class);
        Object invoke = getString.invoke(o,"带参有返回值",1);
        System.out.println(invoke);
    }
    //获取privste成员方法
    public static void getMethod3() throws Exception{
        Class<?> aClass = Class.forName("com.Person");
        Object o = aClass.newInstance();
        Method function = aClass.getDeclaredMethod("function");
        //给私有方法设置权限
        function.setAccessible(true);
        function.invoke(o);
    }
    public static void main(String[] args) throws Exception  {
//        getclass();
//        getAllConstruct();
//        getConstruct1();
//        getConstruct2();
//        getConstruct3();
//        setData();
//        getData();
//        getMethod1();
//        getMethod2();
//        getMethod3();
    }
}

利用反射不改代码更改运行对象

前期准备

创建一个reflect.txt文本和Service1和Service2两个类

reflect.txt文本
在这里插入图片描述
Service1类

public class Service1 {
    public void doService1(){
        System.out.println("执行了Service1的doService1方法");
    }
}

Service2类

public class Service2 {
    public void doService2(){
        System.out.println("执行了Service1的doService2方法");
    }
}

代码实现

 //通过文本改变代码执行所调用的类和方法
    public static void change() throws Exception{
        //reflect.txt中获取类名称和方法名称
        File springConfigFile = new File("E:\\lcy\\project\\APIFuns\\src\\test\\java\\com\\reflect.txt");
        Properties springConfig= new Properties();
        springConfig.load(new FileInputStream(springConfigFile));
        String className = (String) springConfig.get("class");
        String methodName = (String) springConfig.get("method");
        //通过反射获取对象
        Class<?> aClass = Class.forName(className);
        Object o = aClass.newInstance();
        //通过反射获取方法
        Method declaredMethod = aClass.getDeclaredMethod(methodName);
        declaredMethod.invoke(o);
    }

越过泛型检查

使类型为String的list集合添加int类型数据

 //通过反射越过泛型检查
    public static void notCheck() throws Exception{
        ArrayList<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        Method add = list.getClass().getDeclaredMethod("add", Object.class);
        add.invoke(list,5);
        for (Object s : list) {
            System.out.println(s);
        }
    }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值