5反射之对象创建与属性操作

反射之对象创建与属性操作

如何获取运行时类的完整结构

先获取一个类的Class类对象,再通过这个对象的方法来获取,可以获取的结构有Field,Method,Constructor等

方法如下:

获取类的名字
c1.getName(): 包名+类名
c1.getSimpleName(): 类名
获取类的属性
c1.getFields():只能找到public属性
c1.getDeclaredFields():获取全部属性,包括private
获取指定属性的值
c1.getField("name"):因为该属性被private修饰,所以无法获取会报错
c1.getDeclaredField("name")

其他MethodConstructor类似,方法中含有Declared的可以获取全部属性包括private

代码测试

//获取类的信息
public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.reflection.User");

        //获得类的名字
        System.out.println(c1.getName());//com.reflection.User 包名+类名
        System.out.println(c1.getSimpleName());//User 类名

        //获得类的属性
        System.out.println("=============================");
        Field[] fields = c1.getFields();//只能找到public属性
        for (Field field : fields) {
            System.out.println(field);//所以没有输出
        }
        fields = c1.getDeclaredFields();//获取全部属性,包括private
        for (Field field : fields) {
            System.out.println(field);
        }

        //获取指定属性的值
//        Field field = c1.getField("name");//报错,因为属性name为private,无法获取,需要使用getDeclaredField()
        Field field = c1.getDeclaredField("name");
        System.out.println(field);

        //获取类的方法
        System.out.println("=============================");
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("正常的"+method);//输出了所有public方法,包括父类的public方法(Object的)
        }
        methods = c1.getDeclaredMethods();//获得本类的所有方法,包括私有的
        for (Method method : methods) {
            System.out.println("getDeclaredMethods"+method);
        }

        //获得指定方法
        //因为可能有重载方法,所以需要传参数
        System.out.println("=============================");
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得构造器
        System.out.println("=============================");
        Constructor[] constructors = c1.getConstructors();//获得所有public方法
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();//获得所有方法包括private
        for (Constructor constructor : constructors) {
            System.out.println("#"+constructor);
        }
        //获取指定构造器
        System.out.println("=============================");
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println(declaredConstructor);
    }
}

动态创建对象的执行方法

通过反射创建对象

/**

  • 1.调用Class对象的newInstance()方法
  • 1)类必须有一个无参构造器
  • 2)类的构造器访问权限需要足够
  • 2.通过构造器创建对象
  • User user2 = (User)constructor.newInstance(“yuan”, 001, 21);
    */

通过Class对象的newInstance()方法来创建的对象是一个Object类型,需要强转为目标对象类型,如下代码案例中的User

并且其本质是调用目标对象类的无参构造器,如果没有无参构造器或者无参构造器权限不够将会报错

如果目标对象类型没有无参构造,则通过构造器来创建对象,先获取有参构造器的对象,再通过此对象的方法newInstance()传入参数,如下代码:

 Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
 User user2 = (User)constructor.newInstance("yuan", 001, 21);

通过反射操作方法或属性

操作方法:

获取到的方法需要使用invoke方法来激活(也可以理解为在某个对象的某个方法中传参),invoke(对象名,参数),例如代码:

 setName.invoke(user3,"boss");
操作属性:

因为属性一般情况下都是私有的,不能直接操作私有属性,需要关闭权限检测,使用属性的方法setAccessible(true)取消Java语言访问检查,如下代码

 name.setAccessible(true);
 name.set(user4,"boss_yuan");

setAccessible的使用

Method、Field、Constructor对象都有setAccessible()方法。

setAccessible作用是启动和禁用访问安全检查的开关

参数值为true则指示反射的对象在使用时应该取消Java语言访问检查

​ 设置setAccessible(true)可以提高反射效率,如果代码中必须使用反射,而该句代码要频繁的被调用,那么就需要 setAccessible(true)

​ 设置setAccessible(true)使得原本无法访问的私有成员也可以访问

参数为false则指示反射的对象应该实施Java语言访问检查

测试代码

//动态的创建对象,通过反射
/**
 * 1.调用Class对象的newInstance()方法
 * 1)类必须有一个无参构造器
 * 2)类的构造器访问权限需要足够
 * 2.通过构造器创建对象
 * User user2 = (User)constructor.newInstance("yuan", 001, 21);
 */
public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.reflection.User");
        //构造一个对象
        User user = (User)c1.newInstance();//本质上是调用User类的无参构造器,如果没有无参构造器将会报错
        System.out.println(user);

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User)constructor.newInstance("yuan", 001, 21);
        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke激活的意思
        //(对象,"方法的参数")
        setName.invoke(user3,"boss");
        System.out.println(user3.getName());

        //通过反射操作属性
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,需要关闭权限检测,属性或方法的setAccessible(true)
        name.setAccessible(true);
        name.set(user4,"boss_yuan");
        System.out.println(user4.getName());
    }
}
		

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yuan_boss

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

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

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

打赏作者

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

抵扣说明:

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

余额充值