反射

反射机制

反射是一种机制,利用该机制可以在程序运行过程中,对类进行解剖,并获得操作类中的方法,属性,构造成员等。
反射就直接操作class字节码,获得方法,属性,构造成员。

反射是在生成字节码文件之后,对字节码文件进行的操作。

1、获取Class对象的三种方式

//创建测试类试Student
public class Student{
    //属性
    //行为
}

方式1、通过类名.class获取

//格式:类名.class 属性
//常用场景:反射获取方式,确定方法的形参列表类型
public void test01(){
    Class<Student> cls = Student.class;   
}

方式2、通过Object类的成员方法getClass()方法获取

public void test02(){
    Student stu = new Student();
    showInfo(stu);
}
public void showInfo(Object obj){
    // 方式二 : 使用对象名调用 getClass() 方法.
    // 格式 : 对象名.getClass() 方法.
    // 使用场景 : 在方法内部, 确定传入形参的真实类型
    Class<?> cls = obj.getClass();
    System.out.println("cls="+cls)
}

方式3、通过Class.forName(“全限定类名”)方法获取

public void test3() throws ClassNotFoundException {

        // 方式三 : 使用 Class 调用静态方法 forName(全限定类名);   `包名+类名`
        // 使用场景 : 加载外部的配置文件时使用

        Class<?> cls = Class.forName("cn.itcast.test2.Student");
        System.out.println("cls = " + cls);
    }

在获取类对象之后,介绍几个Class类中的常用方法

获取Class中Constructor的相关方法

1.Constructor getConstructor(Class...parameterType);
//根据参数类型获取构造方法对象,只能获得public修饰的构造方法。
//如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。

2.Constructor getDeclaredConstructor(Class...parameter);
//根据参数类型获取构造方法对象,包括private修饰的构造方法。
//如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。

3. Constructor[] getConstructors() ;
//获取所有的public修饰的构造方法

4. Constructor[] getDeclaredConstructors(); 
//获取所有构造方法,包括privat修饰的
Constructor类中的常用方法
1. T newInstance(Object... initargs) 
    //根据指定参数创建对象。
2. void setAccessible(true)
    //暴力反射,设置为可以直接访问私有类型的构造方法。
示例
学生类
public class Student {
    // 属性
    private String name;
    private int age;
    private char gender;

    // 公开构造方法 :
    public Student(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    // 私有构造方法 :
    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 公开无参构造方法
    public Student() {
    }

    // 行为

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }
}
示例方法1

 public void testConstructor1() throws Exception {

        // 1. 获取 Student 类表示的 Class 对象
        Class<?> cls = Class.forName("cn.itcast.test2.Student");

        // 2. 调用 getConstructor 方法
        Constructor<?> constructor = cls.getConstructor(String.class, int.class, char.class);

        // 3. 调用 Constructor 对象的 newInstance 方法, 创建对象
        Object obj = constructor.newInstance("柳岩", 18, '女');

        // 4. 查看创建的对象
        System.out.println("obj = " + obj);
    }
   ```
#### 示例方法2
   ```

        public void testDeclaredConstructor2() throws Exception {

        // 1. 获取 Student 类表示的 Class 对象
        Class<?> cls = Class.forName("cn.itcast.test2.Student");

        // 2. 调用 getDeclaredConstructor 方法
        Constructor<?> constructor = cls.getDeclaredConstructor(String.class, int.class);

        // 3. 暴力反射 (设置可访问权限)
        constructor.setAccessible(true);

        // 4. 调用 Constructor 对象的 newInstance 方法, 创建对象
        Object obj = constructor.newInstance("柳岩", 18);

        // 5. 查看创建的对象
        System.out.println("obj = " + obj);
    }

Class类中与Method相关方法

1. Method getMethod("方法名", 方法的参数类型... 类型)  ;
//根据方法名和参数类型获得一个方法对象,只能是获取public修饰的

2. Method getDeclaredMethod("方法名", 方法的参数类型... 类型);
//根据方法名和参数类型获得一个方法对象,包括private修饰的

3. Method[] getMethods() (了解);
//获取所有的public修饰的成员方法,包括父类中。

4. Method[] getDeclaredMethods() (了解);
//获取当前类中所有的方法,包含私有的,不包括父类中。
method类中的常用方法
1.  Object invoke(Object obj, Object... args) ;
    //根据参数args调用对象obj的该成员方法 
    //如果obj=null,则表示该方法是静态方法

2.  void setAccessible(boolean flag) ;
    //暴力反射,设置为可以直接调用私有修饰的成员方法
示例代码1
    @Test
    public void testMethod1() throws Exception {

        // 1. 获取 Student 类表示的 Class 对象
        Class<?> cls = Class.forName("cn.itcast.test2.Student");

        // 2. 调用 getMethod 方法
        Method eat = cls.getMethod("eat", String.class);

        // 3. 调用 invoke 方法
        Object obj = cls.getDeclaredConstructor().newInstance();
        eat.invoke(obj, "牛肉");
    }

示例代码2
    @Test
    public void testDeclaredMethod2() throws Exception {

        // 1. 获取 Student 类表示的 Class 对象
        Class<?> cls = Class.forName("cn.itcast.test2.Student");

        // 2. 调用 declaredMethod 方法
        Method sleep = cls.getDeclaredMethod("fallInLove");

        // 3. 暴力反射 (设置可访问权限)
        sleep.setAccessible(true);

        // 4. 调用 invoke 执行
        Object obj = cls.getDeclaredConstructor().newInstance();
        sleep.invoke(obj);
    }

Class类中与Field相关方法

1. Field getDeclaredField(String name) ;
//   根据属性名获得属性对象,包括private修饰的

2. Field getField(String name) ;
// 根据属性名获得属性对象,只能获取public修1饰的

3. Field[]  getFields() ;
//    获取所有的public修饰的属性对象,返回数组。

4. Field[]  getDeclaredFields() ;
//  获取所有的属性对象,包括private修饰的,返回数组。
Field类中常用方法
void set(Object obj, Object value) ;
Object get(Object obj)  ;

void setAccessible(true);
//暴力反射,设置为可以直接访问私有类型的属性。
Class getType(); 
//获取属性的类型,返回Class对象
示例代码1
    public void testField1() throws Exception {

        // 1. 获取 Student 类表示的 Class 对象
        Class<?> cls = Class.forName("cn.itcast.test2.Student");

        // 2. 调用 getField 方法
        Field description = cls.getField("description");

        // 3. 设置属性
        Object obj = cls.getDeclaredConstructor().newInstance();
        description.set(obj, "这就是那个神奇的学生.");

        // 4. 获取属性
        Object desc = description.get(obj);
        System.out.println("desc = " + desc);
    }

输出结果 :
desc = 这就是那个神奇的学生.
代码示例2
    @Test
    public void testDeclaredField2() throws Exception {

        // 1. 获取 Student 类表示的 Class 对象
        Class<?> cls = Class.forName("cn.itcast.test2.Student");

        // 2. 调用 getDeclaredField 方法
        Field name = cls.getDeclaredField("name");

        // 3. 暴力反射
        name.setAccessible(true);

        // 4. 设置属性
        Object obj = cls.getDeclaredConstructor().newInstance();
        name.set(obj, "渣渣辉");

        // 5. 查看
        System.out.println(obj);
    }
输出结果 :
Student{name='渣渣辉', age=0, gender= }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值