反射机制 | 通过反射创建对象 | 通过反射机制反编译一个类的属性

反射机制

简介

通过Java语言中的反射机制可以操作字节码文件,反射机制允许程序在执行期间借助ReflectionAPI获取任何类内部的信息,并能直接操作任意对象的内部属性以及方法

反射机制存在java.lang.reflect.*; 包下

反射机制重要的类

  • java.lang.Class:代表整个字节码,代表一个类型,代表整个类。

  • java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。

  • java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法

  • java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。

获取Class实例对象的三种方法

第一种:已知一个类的全名,且该类在类路径下,可以通过Class类的静态方法获取forName()获取

Class c = Class.forName("完整类名");

第二种:已知一个类的实例,调用该实例的getClass()方法获取Class对象

Class c = 引用对象.getClass();

第三种:已知具体的类,通过获取类的class属性

Class c = 任何类.class; 
  • 首先有一个实体类User
package pojo;

public class User {
    private int id;
    public String name;

    public User() {
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
  • 三种获取方式

    import pojo.User;
    public class Demo03 {
        public static void main(String[] args) throws ClassNotFoundException {
            //第一种方法
            Class c = Class.forName("pojo.User");
            System.out.println(c.getName());
    
            //第二种方式
            User user = new User();
            Class c2 = user.getClass();
            System.out.println(c2.getName());
    
            //第三种方式
            Class c3 = User.class;
            System.out.println(c3.getName());
        }
    }
    

可以用Class类的类型为

  • class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
  • interface:接口
  • []:数组
  • enum:枚举
  • annotation:注解
  • primitive type:基本数据类型
  • void
Class c1 = Object.class;//类
Class c2 = Comparable.class;//接口
Class c3 = String[].class;//一维数组
Class c4 = int[][].class;//二位数组
Class c5 = Override.class;//注解
Class c6 = ElementType.class;  //枚举类型
Class c7 = Integer.class; //基本数据类型
Class c8 = void.class;
Class c9 = Class.class;

System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);

//只要元素类型与维度一样,就是同一个Class
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());

image-20211130154344990

通过反射来创建对象

第一种方式:通过调用Class对象的newInstance()方法

  • 类必须含有无参构造器
  • 类的构造器访问权限足够
//第一种方式
Class c1 = Class.forName("pojo.User");
User user = (User)c1.newInstance();
System.out.println(user);//获取类名

第二中方式:通过获得构造器,再通过newInstance来创建对象

//第二种方式
Constructor declaredConstructor = c1.getDeclaredConstructor();//获取构造器
Constructor constructor = c1.getConstructor(int.class,String.class);//获取指定的构造器
User user1 = (User)declaredConstructor.newInstance();
User user2 = (User)constructor.newInstance(1,"1");//传递参数
System.out.println(user1);
System.out.println(user2);

image-20211130155155817

通过反射调用指定的方法

  • 获取类的全名
Class c1= User.class;
System.out.println(c1.getName());//获取类的全名
  • 获取类的全部方法
 Method[] methods = c1.getMethods();//获取类的全部方法
        System.out.println("----获取类的全部方法----");
        for (Method method : methods) {
            System.out.println(method);
        }
  • 获取类的全部属性
  Field[] fields = c1.getDeclaredFields();//获取类的全部属性
        System.out.println("----获取类的全部属性----");
        for (Field field : fields) {
            System.out.println(field);
        }

  • 获取类属性的修饰符列表
 Field[] fields = c1.getDeclaredFields();//获取类的全部属性
System.out.println("----获取类的全部属性----");
for (Field field : fields) {
     int modifiers = field.getModifiers();//返回的修饰符是一个数组,每一个数字是一个修饰符的代号
     //可以将代号转换为字符串-得到属性的修饰符
     String modifierStr = Modifier.toString(modifiers);
     //获取属性的类型
     String simpleName = field.getType().getSimpleName();
     System.out.println(modifierStr + " " + simpleName);
     }

通过反射机制反编译一个类的属性

Class c1= User.class;
//创建对象
User user = (User)c1.newInstance();
//获取指定的类属性
Field name = c1.getField("name");
//给name属性复制
name.set(user,"1");
System.out.println(name.get(user));

对私有属性进行访问的时候,需要打破封装,这里使用setAccessible,设置参数为true

Field id = c1.getDeclaredField("id");
id.setAccessible(true);
id.set(user,1);
System.out.println(id.get(user));

完整的访问代码

package pojo;

import java.lang.reflect.Field;

public class Demo04 {
    public static void main(String[] args) throws Exception {
        Class c1= User.class;
        //创建对象
        User user = (User)c1.newInstance();
        //获取指定的类属性
        Field name = c1.getField("name");
        //给name属性复制
        name.set(user,"1");
        System.out.println(name.get(user));

        Field id = c1.getDeclaredField("id");
        id.setAccessible(true);
        id.set(user,1);
        System.out.println(id.get(user));
        System.out.println(user);
    }
}


name.set(user,"1");
        System.out.println(name.get(user));

        Field id = c1.getDeclaredField("id");
        id.setAccessible(true);
        id.set(user,1);
        System.out.println(id.get(user));
        System.out.println(user);
    }
}

image-20211130162007115

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小七rrrrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值