标签:

概要:最简单优雅的使用反射。

本文的例子都可以在示例代码中看到并下载,如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以提交pull request。本文的示例代码主要是基于jOOR行编写的,如果想了解更多请查看这里的测试代码。

一、需求

今天一个“懒”程序员突然跑过来说:“反射好麻烦,我要提点需求。”

听到这句话后我就知道,今天一定不好过了,奇葩需求又来了。

我们之前写反射都是要这么写:

public static T create(HttpRequest httpRequest) {

Object httpRequestEntity= null;try{

Class httpRequestEntityCls = (Class) Class.forName(HttpProcessor.PACKAGE_NAME + "." +HttpProcessor.CLASS_NAME);

Constructor con= httpRequestEntityCls.getConstructor(HttpRequest.class);

httpRequestEntity=con.newInstance(httpRequest);

}catch(ClassNotFoundException e) {

e.printStackTrace();

}catch(InstantiationException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}catch(NoSuchMethodException e) {

e.printStackTrace();

}catch(InvocationTargetException e) {

e.printStackTrace();

}return(T) httpRequestEntity;

}

因为反射在开发中很少用(做普通的业务开发的话),仅仅在自己写一些框架和注解框架时会用到,所以对api总是不熟悉。每次用到api都要去网上查,查了后又得自己实验下,很不爽。更差劲的是这样写法可读性十分低下。我不希望这样写反射,我希望反射能像

String str = new String();

这样简单,一行代码搞定!。

此外,有很多人都说反射影响性能,在开发的时候要避免用反射。那么什么时候该用反射,什么时候不用反射呢?用什么方式来避免反射呢?如果不明白什么时候用反射,就很难将反射活学活用了。

二、分析

当我们接到上面需求后,我长舒一口气,因为这回的需求还比较简单。

我相信有人会说:“反射就那几个api,一直没变过,你就不会自己去查啊,觉得麻烦就别写代码啊,不知道反射的内部细节你怎么去提高呢?”

其实不然,重复写麻烦的代码和提高自己的代码能力是完全无关的,我实在不知道我们写了成千上万行的findviewById后除了知道类要和xml文件绑定外,还学到了什么。

那么这回我们继续来挑战传统思维和模板式代码,来看看新一代的反射代码应该怎么写,如何用一行代码来反射出类。

在做之前,来看看我们一般用反射来干嘛?

1. 反射构建出无法直接访问的类

2. set或get到无法访问的类变量

3. 调用不可访问的方法

三、解决方案

3.1 一行代码写反射

作为一个Android程序员,索性就拿TextView这个类开刀吧。首先定义一个类变量:

TextView mTv;

通过反射得到实例:

// 有参数,建立类

mTv = Reflect.on(TextView.class).create(this).get();

// 通过类全名得到类

String word = Reflect.on("java.lang.String").create("Reflect TextView").get();

// 无参数,建立类

Fragment fragment = Reflect.on(Fragment.class).create().get();

通过反射调用方法:

// 调用无参数方法

L.d("call getText() : " + Reflect.on(mTv).call("getText").toString());

// 调用有参数方法

Reflect.on(mTv).call("setTextColor", 0xffff0000);

通过反射get、set类变量

TextView中有个mText变量,来看看我们怎么接近它。

// 设置参数

Reflect.on(mTv).set("mText", "---------- new Reflect TextView ----------");

// 获得参数

L.d("setgetParam is " + Reflect.on(mTv).get("mText"));

3.2 什么时候该用反射,什么时候不用反射

又到了这样权衡利弊的时候了,首先我们明确,在日常开发中尽量不要用反射,除非遇到了必须要通过反射才能调用的方法。比如我在做一个下拉通知中心功能的时候就遇到了这样的情况。系统没有提供api,所以我们只能通过反射进行调用,所以我自己写了这样一段代码:

private static voiddoInStatusBar(Context mContext, String methodName) {try{

Object service= mContext.getSystemService("statusbar");

Method expand=service.getClass().getMethod(methodName);

expand.invoke(service);

}catch(Exception e) {

e.printStackTrace();

}

}/*** 显示消息中心*/

public static voidopenStatusBar(Context mContext) {//判断系统版本号

String methodName = (VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";

doInStatusBar(mContext, methodName);

}/*** 关闭消息中心*/

public static voidcloseStatusBar(Context mContext) {//判断系统版本号

String methodName = (VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels";

doInStatusBar(mContext, methodName);

}

先来看看利用jOOR写的doInStatusBar方法会简洁到什么程度:

private static voiddoInStatusBar(Context mContext, String methodName) {

Object service= mContext.getSystemService("statusbar");

Reflect.on(service).call(methodName);

}

哇,就一行代码啊,很爽吧~

爽完了,我们就来看看反射问题吧。因为不是系统给出的api,所以谷歌在不同的版本上用了不同的方法名来做处理,用反射的话我们就必须进行版本的判断,这是需要注意的,此外反射在性能方面确实不好,这里需要谨慎。

我的建议:

如果一个类中有很多地方都是private的,而你的需求都需要依赖这些方法或者变量,那么比起用反射,推荐把这个类复制出来,变成自己的类,像是toolbar这样的类就可以进行这样的操作。

在自己写框架的时候,我们肯定会用到反射,很简单的例子就是事件总线和注解框架,翔哥就说过一句话:无反射,无框架。也正因为是自己写的框架,所以通过反射调用的方法名和参数一般不会变,更何况做运行时注解框架的话,反射肯定会出现。在这种情况下千万不要害怕反射,索性放心大胆的做。因为它会让你完成很多不可能完成的任务。

总结下来就是:

实际进行日常开发的时候尽量少用反射,可以通过复制原始类的形式来避免反射。在写框架时,不避讳反射,在关键时利用反射来助自己一臂之力。

四、后记

我们终于完成了用一行代码写反射,避免了很多无意义的模板式代码。需要再次说明的是,本文是依据jOOR 进行编写的,这里有原项目readme的中文翻译。

jOOR是我无意中遇到的开源库,第一次见到它时我就知道这个是我想要的,因为那时候我被反射搞的很乱,而它简洁的编码方式给我带来了新的思考,大大提高了代码可读性。顺便一说,作者人比较好(就是死活不愿意让我放入中文的readme),技术也很不错。该项目有很详细的测试用例,并且还给出了几个类似的反射调用封装库。可见作者在写库时做了大量的调研和测试工作,让我们可以放心的运用该库(其实就两个类)。

本文希望带给大家一个反射的新思路,给出一个最简单实用的反射写法,希望能被大家迅速运用到实践中去。更加重要的是,通过对jOOR的分析,让我知道了写库前应该调研类似的库,而不是完全的创造新轮子,调研和测试是代码稳定性的重要保障。

标签:

java反射最佳实践_Java 反射最佳实践 – 码农网相关推荐

  1. Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网

    线程池的详解 Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网 http://www.codeceo.com/article/java-threadpool-exec ...

  2. java反射的原理_java反射机制的实现原理

    java反射机制的实现原理 反射机制: 所谓的反射机制就是java语言在运行时拥有一项自观的能力. 通过这种能力可以彻底的了解自身的情况为下一步的动作做准备. 下面具体介绍一下java的反射机制.这里 ...

  3. java反射 数组类型_Java反射-数组

    通过反射使用数组有时会比较棘手.特别是需要获得一个特定类型数组的Class对象,如int[]等.本文将讨论如何通过反射创建数组和获得他们的Class对象. 注意:本文在阅读Eyal Lupu的博客&q ...

  4. java反射随意值_Java反射总结

    能够分析类能力的程序称为反射.对于给定的Java类名,可以通过反射获取类的信息.将类的各成分映射出相应的Java类. Class类 在程序运行期间,Java运行时系统始终对所有的对象维护一个被称为运行 ...

  5. java反射创建实例_Java反射创建实例

    Java反射创建实例 package com.wkcto.chapter08.demo02; import java.lang.reflect.Constructor; import java.lan ...

  6. java 反射 工厂模式_Java反射机制demo(七)—反射机制与工厂模式

    Java反射机制demo(七)-反射机制与工厂模式 工厂模式 简介 工厂模式是最常用的实例化对象模式. 工厂模式的主要作用就是使用工厂方法代替new操作. 为什么要使用工厂模式?直接new不好吗? 直 ...

  7. java try catch陷阱_Java异常处理最佳实践及陷阱防范

    原标题:Java异常处理最佳实践及陷阱防范 出自<深夜里的程序猿> 作者:wangzenghuang 前言 不管在我们的工作还是生活中,总会出现各种"错误",各种突发的 ...

  8. java class 静态模块_Java API 最佳设计实践:在模块化和非模块化 Java 环境中使用...

    了解在设计 Java API 时应该运用的一些 API 设计实践.这些实践通常很有用,而且可确保 API 能在诸如 OSGi 和 Java Platform Module System (JPMS) ...

  9. java并发编程实践_Java并发编程实践如何正确使用Unsafe

    一.前言 Java 并发编程实践中的话: 编写正确的程序并不容易,而编写正常的并发程序就更难了.相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各 ...

最新文章

  1. 【转载】大连商品交易所-新套利撮合算法FAQ
  2. socket的阻塞非阻塞方法在缓冲区的差别
  3. Java获取系统文件类型图标并显示在JSP上
  4. Fedora 17 安装视频
  5. 不同域名指向一个Web站点,ICP证如何设置
  6. python 类变量 none 内存泄露_Python中使用自定义类class作为海量数据结构时内存占用巨大的问题...
  7. 前端知识整理 CSS盒模型
  8. 天池学习赛:工业蒸汽量预测1——数据探索
  9. python重构迭代_Pylint:让你的 Python 代码保持一致
  10. 唯众高职人工智能技术应用专业解决方案
  11. 【转载】vue项目部署到阿里云上详解
  12. 阿里滑块 x82y x5sec本地dll 易语言
  13. 普华商业集团受邀出席2020年长三角区块链技术与产业高端研讨会
  14. 基于Python的经纬度与xy坐标系相互转换
  15. python是什么?能干什么
  16. jquery 垂直无限轮播
  17. Help!我的数据库坏了,怎么办?
  18. Mac 与 Linux Windows 常见使用区别
  19. 第3课:Scratchjr功能按钮
  20. cad文件管理服务器,通用CAD图纸文件管理安全软件(SafeShare)

热门文章

  1. service network restart重启失败_NodeManager 启动失败问题处理
  2. c语言的简单程序设计实验报告,工程学院C语言程序设计实验报告
  3. Python Imaging Library: ImageOps Module(图像运算模块)
  4. 对 React 组件进行单元测试(unit testing)
  5. MySQL的sql优化
  6. 老王学linux-系统安全
  7. 联合光伏回应“天价收购”质疑:并非每瓦10.24元
  8. RDS SQL Server死锁(Deadlock)系列之四利用Service Broker事件通知捕获死锁
  9. 关于安装 rst2pdf 时遇到的 setuptools过老的问题
  10. SpringMVC+Spring3+Hibernate4