Java反射详解及扩展应用

本文深入解析Java反射机制,包括如何动态获取类的信息和调用方法,以及反射与Annotation的结合使用,适合Java开发者深入了解和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情

反射概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
这里需要说到Java有两种对象,一个是Class对象,也就是类对象,还有一个是实例对象。实例对象就是通过Class对象创建出来的。
而反射就是针对Class对象进行的处理。

获取Class对象

我们知道java代码运行时,需要首先将java代码编译成二进制字节码,保存在.class文件中,然后JVM将.class文件载入内存,并且创建一个对应的Class对象。
获取Class对象有以下三种方式:
1、通过类名获取Class

Class userClass = User.class;

2、通过实例对象获取Class

User user = new User();
Class userClass = user.getClass();

3、通过完成类名路径获取Class

try {
            Class userClass = Class.forName("com.androidwind.demo.reflection.User");
        } catch (ClassNotFoundException e) {
            Log.e(TAG, e.toString());
        }

通过Class对象获取实例对象

Class userClass = Class.forName("com.androidwind.demo.reflection.User");
Object useObj = userClass .getConstructor().newInstance();

通过Class对象获取类所有方法

//获取Class对象
Class userClass = Class.forName("com.androidwind.demo.reflection.User");
//获取所有共有方法
userClass.getMethods();  
Method[] methodArray = userClass.getMethods();  
for(Method m : methodArray){  
    System.out.println(m);  
}
//获取私有、受保护、默认方法
methodArray = userClass.getDeclaredMethods();  
for(Method m : methodArray){  
    System.out.println(m);  
}
//获取公有方法并调用
Method m = userClass.getMethod("setName", String.class);  
Object obj = userClass.getConstructor().newInstance();  
m.invoke(obj, "王五");  
//获取私有方法并调用
m = userClass.getDeclaredMethod("setAge", int.class);
m.setAccessible(true);
Object result = m.invoke(obj, 20);

通过Class对象获取类所有属性

//获取Class对象
Class userClass = Class.forName("com.androidwind.demo.reflection.User");
//获取公有字段
Field[] fieldArray = userClass.getFields();
for(Field f : fieldArray){
    System.out.println(f);
}
 //获取私有、受保护、默认字段
 fieldArray = userClass.getDeclaredFields();
for(Field f : fieldArray){
     System.out.println(f);
}
//获取共有字段并赋值
Field f = userClass.getField("name");
Object userObj = userClass.getConstructor().newInstance();
f.set(userObj, "张三");
//获取私有字段并赋值
f = userClass.getDeclaredField("age");
f.setAccessible(true);
f.set(obj, 18);

扩展:反射与Annotation

通过反射获取的Method有两个关于Annotation的属性:
isAnnotationPresent:判断Annotation是不是某个类型;
getAnnotation:获取Annotation的值;
比如android-tiny-bus项目:
通过Subscriber这个Annotation标注threadMode是一个后台线程接收。

@Subscriber(threadMode = ThreadMode.BACKGROUND)
    public void onEvent(TestBackgroundEvent event) {
        System.out.println("[onEvent]Current thread id is: " + Thread.currentThread().getId());
        if (isMainThread()) {
            ((TextView) findViewById(R.id.tv_hello)).setText("update in main thread");
        } else {
            ((TextView) findViewById(R.id.tv_hello)).setText("update in background thread");
        }
    }

注册的时候会通过反射方法获取Annotation:

@Override
    public void register(Object object) {
        if (object == null) return;
        Class cls = object.getClass();//获取类实例(即类信息)
        Method[] methods = cls.getDeclaredMethods();//获取类实例的public方法
        for (Method method : methods) {
            if (method.isAnnotationPresent(Subscriber.class) &&//判断方法是否是Subscriber注释
                    method.getParameterTypes() != null//获取方法的传入参数类型
                    && method.getParameterTypes().length == 1) {//只有一个参数
                TinyHandler tinyHandler = new TinyHandler();
                tinyHandler.setMethodName(method.getName());
                tinyHandler.setObject(object);
                Subscriber subscriber = method.getAnnotation(Subscriber.class);
                System.out.println("subscriber = " + subscriber.threadMode());
                tinyHandler.setThreadMode(subscriber.threadMode());
                TinyBusManager.getInstance().add(method.getParameterTypes()[0], tinyHandler);
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值