如何创建反射以及通过反射拿到值


前言

本文介绍了创建反射的三种方式,主要了解如何通过反射获取对象中的构造器、成员变量和成员方法。


一、反射是什么?

反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。

二、获取反射的三种方式

直接使用类名.class获取:Class c1 = 类名.class
调用Class提供的方法:Class c2 = Class.forName(“全类名”)
调用Object提供的方法:Class c3 = 对象.getClass()

代码如下:


/*
反射的第一步是什么
    获取Class类对象,如此才可以解析类的全部成分

获取Class对象的三种方式
    1. 直接使用类名.class获取:Class c1 = 类名.class
    2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
    3. 调用Object提供的方法:Class c3 = 对象.getClass()
*/
public class Demo1 {
    public static void main(String[] args) throws Exception {
        Class<Cat> catClass = Cat.class;
        Class<?> aClass = Class.forName("com.itheima.b_反射.Cat");
        Class<? extends Cat> aClass1 = new Cat().getClass();
       
    }

}

三、获取类的构造器

获取构造器[下面是Class的方法]
Constructor<?>[] getConstructors() 获取所有的公共构造器(只能获取public修饰的) Constructor<?>[] getDeclaredConstructors() 获取全部构造器(只要存在就能拿到)
Constructor getConstructor(Class<?>... parameterTypes) 获取某个公共构造器(只能获取public修饰的) Constructor getDeclaredConstructor(Class<?>… parameterTypes) 获取某个构造器(只要存在就能拿到)
使用构造器(创建对象)[下面是Constructor的方法]
T newInstance(Object… initArgs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)

注意
使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)

代码如下:


public class Cat {
    public static int a;
    public static final String COUNTRY = "中国";
    private String name;
    private int age;

    public Cat(){
        System.out.println("无参数构造器执行了~~");
    }

    public Cat(String name){
        System.out.println("无参数构造器执行了~~");
        this.name = name;
    }

    private Cat(String name, int age) {
        System.out.println("有参数构造器执行了~~");
        this.name = name;
        this.age = age;
    }

    private void run(){
        System.out.println("🐱跑的贼快~~");
    }

    public void eat(){
        System.out.println("🐱爱吃猫粮~");
    }

    private String eat(String name){
        return "🐱最爱吃:" + name;
    }

    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;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Demo2 {

    public static void main(String[] args) throws Exception {
        Class<Cat> catClass = Cat.class;
        System.out.println(catClass.getName());
        Constructor[] constructors = catClass.getConstructors();
        for (Constructor constructor:constructors) {
            System.out.println(constructor);
        }
        System.out.println("------------------");
        Constructor<?>[] declaredConstructors = catClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("------------------");
        Constructor<Cat> constructor = catClass.getConstructor();
        System.out.println(constructor);
        System.out.println("------------------");
        Constructor<Cat> constructor1 = catClass.getConstructor(String.class);
        Cat cat = constructor1.newInstance("猫");
        System.out.println(cat);

        Constructor<Cat> declaredConstructor = catClass.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        System.out.println(declaredConstructor.newInstance("小猫", 23));
    }
}

四、获取类的成员变量

获取成员变量[Class提供]
public Field[] getFields() 获取类的所有公共成员变量(只能获取public修饰的)
public Field[] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到)
public Field getField(String name) 获取类的某个公共成员变量(只能获取public修饰的)
public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)

使用成员变量(赋值和取值) [Field提供]
public void set(Object obj, Object value): 赋值
public Object get(Object obj): 取值
public void setAccessible(boolean flag): 设置为true,表示禁止检查访问控制(暴力反射)

注意
使如果想使用private修饰的变量,需要暴力反射

public class Demo3 {
    public static void main(String[] args) throws Exception {
        Cat cat = new Cat();
        Class<? extends Cat> aClass = cat.getClass();

        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
            Object o = field.get(cat);
            System.out.println(o);
        }
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            System.out.println(declaredField.get(cat));
        }
        System.out.println(aClass.getField("COUNTRY").get(cat));
        Field names = aClass.getDeclaredField("name");
        names.setAccessible(true);
        System.out.println(names.get(cat));
    }

}

五、获取类的成员方法

获取成员方法[Class提供]
Method[] getMethods() 获取类的全部公共成员方法(只能获取public修饰的)
Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能拿到)
Method getMethod(String name, Class<?>... parameterTypes) 获取类的某个公共成员方法(只能获取public修饰的) Method getDeclaredMethod(String name, Class<?>… parameterTypes) 获取类的某个成员方法(只要存在就能拿到)

使用成员方法(执行方法)[Method提供]
public Object invoke(Object obj, Object… args) 触发某个对象的该方法执行。
public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)

注意
使如果想使用private修饰的成员方法,需要暴力反射

public class Demo4 {
    public static void main(String[] args) throws Exception {
        Class catClass = Cat.class;
        Method[] methods = catClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName() +"--------"+ method.getReturnType()+"--------" + method.getParameterCount());
        }
        Method[] declaredMethods = catClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method.getName() +"--------"+ method.getReturnType()+"--------" + method.getParameterCount());
        }
        Method eat = catClass.getMethod("eat");
        Method eat1 = catClass.getDeclaredMethod("eat", String.class);
        Cat cat = new Cat();
        System.out.println(eat.invoke(cat));
        eat1.setAccessible(true);
        Object invoke = eat1.invoke(cat,"肉");
        System.out.println(invoke);
    }
}

总结

三种创建反射的方式熟练掌握,学会拿到对象的构造器、成员变量和成员方法,拿到这三个的方式差不多,方法不一样但都有规律,很容易记住。

  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值