Android 使用Java的反射机制总结

导语

 

 

反射是一种具有与Java类进行动态交互能力的一种机制,在Java和Android开发中,一般需要访问隐藏属性或者调用方法改变程序原来的逻辑时会用到,这个比较常见,由于一些原因,系统并没有开放一些接口出来,这个时候利用反射是一个有效的解决方法,这个下文会有案例去讲;另外常见的注解框架也是在运行时利用反射机制来获取的。在模块化和插件化开发中更离不开反射,离开了反射它什么也做不了。

 

一、定义

 

关于反射的定义,已经成文的是这样介绍:

 

Java的反射机制是在运行的状态中,对于任意一个类,都能够这个类的所有属性和方法;对于任意一个对象,都能够调用任何方法和属性;像这种动态获取信息以及动态调用对象方法的功能成为Java的反射机制。

 

这段话说的是简介精辟,算上对反射的总结了。那我们发现有几个强调词,“运行”、“任意”、“动态”等,为什么用这几个词来形容呢?我换句话来解释,因为是在程序运行状态下才会把类加载到Java虚拟机的内存中,这属于类的动态加载,并非发生在编译时候,所以,也就可以把内存中不存在的任意类动态加载进来,并且可以获取和修改任意类的信息。总之,在运行状态下利用反射可以动态的和任意类进行交互。

 

二、组成使用

 

关系组成图:

  • java.lang.Class.java:   类对象;
  • java.lang.reflect.Constructor.java: 类构造器;(注意:反射的类必须有构造函数!!!)
  • java.lang.reflect.Method.java:   类方法;
  • java.lang.reflect.Field.java:   类属性;

 

1、反射获取类的实例化对象:(三种方法)

 

Class<?> cls=Class.forName("com.fanshe.Person"); //forName(包名.类名)
Person p=(Person)cls.newInstance();
或
Person p = new Person();
Class<?> cls=p.getClass();
Person p2=(Person)cls.newInstance();
或
Class<?> cls=Person.Class();
Person p=(Person)cls.newInstance();

 

2、反射获取类的构造器:

 

Constructor constructors = cls.getDeclaredConstructor(String.class);//参数根据类的构造,这里假设包含String类型

Object newclass = constructors.newInstance("构造实例并赋值");

3、反射获取类的方法和返回值:

 

Method getMethod = cls.getDeclaredMethod(methodName);//传入方法名
Object invokeMethod =getMethod.invoke(newclass);//传入实例值
静态方法不用借助实例 
Method getMethod = cls.getDeclaredMethod(methodName);
Object invokeMethod =getMethod.invoke(null);

 

4、反射获取类的属性的值:

 

Field getField = cls.getDeclaredField(fieldName);//传入属性名
Object getValue =getField.get(newclass);//传入实例值
       静态属性不用借助实例 
Field getField = cls.getDeclaredField(fieldName);
Object getValue =getField.get(null);

三、工作原理

 

我们知道,Java的每个.class文件里承载了类的所有信息内容,包含基佬父类、接口、属性、构造、方法等;这些class文件会在程序运行状态下通过ClassLoad类机制加载到虚拟机内存中并产生一个对象实例,然后这个对象就可以对这块内存地址进行引用;一般我们通过New一个对象创建就行,而利用反射我们通过JVM查找并指定加载的类名,就可以创建对象实例,而在java中,类的对象被实例化可以在内存中被引用时,就可以获取该类的所有信息,就也就是不成文的规矩吧。

 

四、小案例

 

看完了前面的讲解,我们再来看一个小案例来加深认识,一起实践一下。

 

public class Student {
    private int age;
    private String name;
    private static String mStatic;//静态属性
    /**
     * 无参构造
     */
    public Student() {
        throw new IllegalAccessError("使用默认构造函数会报错");
    }
    /**
     * 有参构造
     * @param age 年龄
     * @param name 姓名
     */
    private Student(int age, String name) {
        this.age = age;
        this.name = name;
        mStatic = "静态反射";
    }
    private String getName() {
        return name;
    }
    /**
     * 静态带返回值方法
     * @return String
     */
    private static String getTest() {
        return mStatic;
    }
}

 

这个类用到了Private私有修饰,包含带参构造函数、普通属性和静态属性,以及静态方法。

 

public void Student() throws Exception{
    Class<?> clazz = Class.forName("com.example.javafanshe.Student");
    Constructor constructors = clazz.getDeclaredConstructor(int.class, String.class);
    constructors.setAccessible(true);//可访问私有为true
    //利用构造器生成对象
    Object mStudent = constructors.newInstance(22, "大头");
    Log.d("log","构造器是否报错:"+mStudent.toString());
    //获取隐藏的int属性
    Field mField = clazz.getDeclaredField("age");
    mField.setAccessible(true);
    int age = (int) mField.get(mStudent);
    Log.d("log","年龄为:"+age);
    //调用隐藏的方法
    Method getMethod = clazz.getDeclaredMethod("getName");
    getMethod.setAccessible(true);
    String newname = (String) getMethod.invoke(mStudent);
    Log.d("log","名字为:"+newname);
    //调用静态方法
    Method getStaticMethod = clazz.getDeclaredMethod("mStatic");
    getStaticMethod.setAccessible(true);
    String result = (String) getStaticMethod.invoke(null);
    Log.d("log","调用静态方法:"+result);
}

 

结果日志Log如下。

 

 

01-12 19:17:00.282 31564-31564/? D/log: 构造器是否报错:com.example.javafanshe.Student@42055ca0
01-12 19:17:00.282 31564-31564/? D/log: 年龄为:22
01-12 19:17:00.282 31564-31564/? D/log: 名字为:大头
01-12 19:17:00.282 31564-31564/? D/log: 调用静态方法:静态反射

 

五、总结

 

     写到这里,关于反射的介绍和使用都讲的差不多了,算是适合初学者比较轻松的认识反射吧,当然反射的使用远没有上面案例那么简单,实际使用还得需要多规范的组织一下,不能只为了实现功能,不顾代码的可读性和可维护性。另外,最好多用public来修饰,以防兼容版本风险,还有第三方开源的项目也要注意,不知道哪里突然维护修理了源码,也会出现兼容问题。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

艾阳Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值