反射

什么是反射

动态获取的信息以及动态调用对象的方法的功能称为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]

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/xwb583312435/p/8691878.html