• 反射


    什么是反射

    动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

     

    什么时候使用反射

    传一个对象

    传一个字节码对象

    传一个全限类名

     

    优点

    1、反射提高了程序的灵活性和扩展性。

    2、降低耦合性,提高自适应能力。

    3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

     

    缺点

    1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。

    2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

     

    反射条件

    运行状态

     

    实例一

    通过反射存放String类型的对象

    import java.lang.reflect.Method;
    import java.util.ArrayList;
    
    /**
     * 通过反射存放String类型的对象
     * 
     * @author admin
     *
     */
    public class Demo4 {
        public static void main(String[] args) {
            try {
                ArrayList<Integer> list = new ArrayList<>();
                list.add(1000000);
                System.err.println(list);
                // 通过反射获取List集合的字节码对象
                Class<?> clazz = Class.forName("java.util.ArrayList");
                // 通过反射获取addMethod方法
                Method method = clazz.getMethod("add", Object.class);
                // 通过反射调用method方法
                method.invoke(list, "薛栋榕,我的小宝贝");
                System.err.println(list);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    运行结果:

    [1000000]
    [1000000, 薛栋榕,我的小宝贝]

     

    实例二

    创建一个对象student

    package cn.zbx.test.method;
    
    public class Student {
        private int age;
        private String name;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Student [age=" + age + ", name=" + name + "]";
        }
    
    }

    方式一:

    import java.lang.reflect.Field;
    
    public class Demo5 {
        public static void main(String[] args) {
            try {
                // 获取student类的字节码对象
                Class<?> clazz = Class.forName("cn.zbx.test.method.Student");
                // 1.利用反射创建一个空的对象
                Student student = (Student) clazz.newInstance();
                // 2.获取字段
                Field ageField = clazz.getDeclaredField("age");
                Field nameField = clazz.getDeclaredField("name");
                // 3.设置私有属性
                ageField.setAccessible(true);
                nameField.setAccessible(true);
                // 4.给字段设置值
                ageField.set(student, 30);
                nameField.set(student, "jack");
                System.out.println(student.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }

    运行结果:

    Student [age=30, name=jack]

    方式二:

    import java.lang.reflect.Method;
    
    public class Demo6 {
        public static void main(String[] args) {
            try {
                // 获取student类的字节码对象
                Class<?> clazz = Class.forName("cn.zbx.test.method.Student");
                // 1.利用反射创建一个空的对象
                Student student = (Student) clazz.newInstance();
                // 2.通过反射获取set方法
                Method setAgeMethod = clazz.getMethod("setAge", int.class);
                Method setNameMethod = clazz.getMethod("setName", String.class);
                // 3.赋值
                setAgeMethod.invoke(student, 100);
                setNameMethod.invoke(student, "反射获取set方法");
                System.out.println(student);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    运行结果:

    Student [age=100, name=反射获取set方法]

    方式三:

    package cn.zbx.test.method;
    
    public class Student {
        public Student(int age, String name) {
            super();
            this.age = age;
            this.name = name;
        }
    
        private int age;
        private String name;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Student [age=" + age + ", name=" + name + "]";
        }
    
    }
    package cn.zbx.test.method;
    
    import java.lang.reflect.Constructor;
    
    public class Demo7 {
        public static void main(String[] args) {
            try {
                // 获取student的字节码文件
                Class<Student> clazz = Student.class;
                // 获取有参构造
                Constructor<Student> constructor = clazz.getConstructor(int.class, String.class);
                Student newInstance = constructor.newInstance(100, "李四");
                // "李四被实例化");
                System.out.println(newInstance);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    运行结果:

    Student [age=100, name=李四]

    创建一个类对象并调用对象的方法

    package cn.zbx.test.method;
    
    public class Test1 {
        public void print(String str){
            System.out.println("hello---------------"+str);
        }
    }
    package cn.zbx.test.method;
    
    import java.lang.reflect.Method;
    
    public class Demo8 {
        public static void main(String[] args) {
            try {
                // 获取TEST1的字节码文件对象
                Class<?> clazz = Class.forName("cn.zbx.test.method.Test1");
                // 利用反射技术获取对象
                Test1 newInstance = (Test1) clazz.newInstance();
                // 利用反射技术获取print方法
                Method printMethod = clazz.getMethod("print", String.class);
                // 利用反射调用print方法:printMethod.invoke(obj, args);
                printMethod.invoke(newInstance, "java工程师__薛文博");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    运行结果:

    hello---------------java工程师__薛文博

    实例三

    javaBean赋值

    定义一个标准的JavaBean,名叫Person,包含属性name、age。

    使用反射的方式创建一个实例、调用构造函数初始化name、age,使用反射方式调用setName方法对名称进行设置,

    不使用setAge方法直接使用反射方式对age赋值

    package cn.zbx.test.method;
    
    public class Person {
        private int age;
        private String name;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Person(int age, String name) {
            super();
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person [age=" + age + ", name=" + name + "]";
        }
    
    }
    package cn.zbx.test.method;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Demo11 {
        public static void main(String[] args) {
            try {
                // 1.获取person的字节码文件
                Class clazz = Person.class;
                // 2.利用反射获取有参构造方法
                Constructor constructor = clazz.getConstructor(int.class, String.class);
                // 3.调用构造方法给属性初始化
                Person person = (Person) constructor.newInstance(20, "薛文博1");
                System.out.println("1--------" + person);
                // 4.利用反射调用setName()方法对名称初始化
                Method setNameMethod = clazz.getMethod("setName", String.class);
                setNameMethod.invoke(person, "薛文博2");
                System.out.println("2--------" + person);
                // 5.不是使用setAge方法直接反射方式对Age初始化
                Field ageField = clazz.getDeclaredField("age");
                ageField.setAccessible(true);
                ageField.set(person, 18);
                System.out.println("3--------" + person);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    运行结果:

    1--------Person [age=20, name=薛文博1]
    2--------Person [age=20, name=薛文博2]
    3--------Person [age=18, name=薛文博2]

     

     

     

     

     

     

     

  • 相关阅读:
    园 首页 新随笔 联系 管理 订阅 订阅 RTSP协议转换RTMP直播协议
    sequence diagram
    Model Binding
    asp.net mvc
    系统日志和异常的处理①
    随机森林之oob error 估计
    Extjs相关知识点梳理
    Extjs报错处理
    webbrowser在html中写入内容并添加js
    tcpdump一个命令的剖析
  • 原文地址:https://www.cnblogs.com/xwb583312435/p/8691878.html
Copyright © 2020-2023  润新知