为什么需要反射

关于反射有很多场景可能会用到,这里用到是因为有一些私有方法必须要写单元测试。
关于为什么会对私有方法进行单元测试,也许这并不是常见的需求。然而当外部环境变化很大(比如网站的url)时,保证你的函数正确有助于快速排错。

对私有方法反射的主要流程

1.首先获得方法A所在类的Class object,即通过Class.forName(ClassName)以及 object.newInstance()获得。

注意这里的ClassName包含类所在的包名。

2.利用刚才得到的Class object调用getDeclaredMethod(String name, Class<?>... parameterTypes)方法。前一个参数是nonpublic方法A的名字,后面的参数是包含方法A的各个参数的类型的Class Object。这样就可以得到方法A的object,原文描述为:Returns a Method object that reflects the specified declared method of the class or interface represented by this Class object。

Method A’= getDeclaredMethod(“A”,Class<?>... parameterTypesOf”A”) 也可以保留方法A原名,这里为了区分命名为A’。

3.设置方法A’的可见性A’.setAccessible(true);

4.调用A’方法,注意一定要invoke()====>A’.invoke(A所在类的Classobject, A的参数)。

对私有字段反射的主要流程

1.和私有方法的反射类似

2.利用刚才得到的Class object调用getDeclaredField(String fieldName)获取字段对象fieldObj。

3.设置字段可见性fieldObj.setAccessible(true);

4.设置字段fieldObj.set(object, value)

获取字段的值fieldObj.get(object)

一个基本和典型的私有方法反射示例

    (1)写个类
    package xxx.yyy.zzzpublic class Simple {private void displayMessage(String strMsg) {System.out.println("message is:" + strMsg);}}
    (2)反射调用import java.lang.reflect.*;public class Test {public static void main(String[] args) throws ClassNotFoundException,SecurityException, NoSuchMethodException, InstantiationException,IllegalAccessException, IllegalArgumentException,InvocationTargetException {Class simpleClass = Class.forName("xxx.yyy.zzz.Simple");Object simpelObject = simpleClass.newInstance();Class[] args1 = new Class[1];args1[0] = String.class;Method simpleMethod = simpleClass.getDeclaredMethod("displayMessage",arg1);simpleMethod.setAccessible(true);String[] argments = new String[1];argments[0] = "Hello,world";simpleMethod.invoke(simpelObject, argments);}}

复杂参数类型的反射示例

这里才是重点!
通常invoke返回值是Object对象,通过对它强制类型转换可以得到复杂类型的返回值,比如数组,集合等等(当然前提是你强制转换的类型和你的函数定义一致)。
先放一个数组的例子,假设有如下的类:
package org.apache.nutch.parse.html;public class TestOnly {private String[] array= new String[4];private String[] getStringArray(){return array;}private void setStringArray(String[] values){array=values;}}

它的array数据和对应的set/get方法都是私有的

package org.apache.nutch.parse.html;import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;import static org.junit.Assert.*;public class TestOnlyTest {@Testpublic void testGetStringArray() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,IllegalAccessException, InstantiationException, MalformedURLException, NoSuchFieldException {Class testObj = Class.forName("org.apache.nutch.parse.html.TestOnly");Object obj = testObj.newInstance();/*test set method.*/Method setArray = testObj.getDeclaredMethod("setStringArray", new Class[]{String[].class});setArray.setAccessible(true);String[] name = {"hello", "world"};setArray.invoke(obj, new Object[]{name});/*test get method.*/Method getArray = testObj.getDeclaredMethod("getStringArray");getArray.setAccessible(true);String[] result = (String[])getArray.invoke(obj);assertEquals("hello",result[0]);assertEquals("world",result[1]);/*test private field visit.*/Field array =testObj.getDeclaredField("array");array.setAccessible(true);array.set(obj, new String[]{"come","here","baby"});result = (String[])array.get(obj);assertEquals("come",result[0]);assertEquals("here",result[1]);assertEquals("baby",result[2]);}
}

当然不用单元测试,也可以用通过打印语句来验证结果集的正确性。

再放一个工作中实际用到的小例子。
自定义nutch的解析类 实现Parser接口定义的抽象方法如下:
    @Overridepublic ArrayList<Outlink> filterOutlinks(ArrayList<Outlink> list) {ArrayList<Outlink> filterList = new ArrayList<Outlink>();Outlink filterLink = null;for (Outlink outlink : list) {if (isCrawlOutLineUrl(outlink.getToUrl())) {try {filterLink = new Outlink(outlink.getToUrl(), "ydss");} catch (MalformedURLException e) {dMsg.warn("MalformedURLException:", e);continue;}if (!filterList.contains(filterLink)) {filterList.add(filterLink);}}}return filterList;}

其中isCrawlOutLineUrl是一个判断是否为合法出链的私有方法,具体逻辑忽略,此外用到了一个私有字段url。

对应的单元测试如下:
//    @Testpublic void testIsCrawlOutLineUrl() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,IllegalAccessException, InstantiationException, NoSuchFieldException{String outLinkUrl = "http://bbs.ydss.cn/thread-199593-1-1.html";Class ypObj = Class.forName("org.apache.nutch.parse.html.YdssParser");Object yp = ypObj.newInstance();Method isCrawlOutLineUrl = ypObj.getDeclaredMethod("isCrawlOutLineUrl", new Class[]{String.class});isCrawlOutLineUrl.setAccessible(true);Field url = ypObj.getDeclaredField("url");url.setAccessible(true);url.set(yp, "http://bbs.ydss.cn/forum.php?mod=viewthread&tid=505896&extra=page%3D1%26filter%3Dauthor%26orderby%3Ddateline");assertFalse((Boolean) isCrawlOutLineUrl.invoke(yp, outLinkUrl));outLinkUrl = "http://bbs.ydss.cn/thread-505896-1-1.html";assertFalse((Boolean) isCrawlOutLineUrl.invoke(yp, outLinkUrl));}
以上是最近写私有方法和字段的单元测试所获的一些心得,分享,备忘。

Java反射 二三事相关推荐

  1. Java学习之二-Java反射机制

    问题: 在运行时,对一个JAVA类,能否知道属性和方法:能否调用它的任意方法? 答案是可以的,JAVA提供一种反射机制可以实现. 目录 什么是JAVA的反射机制 JDK中提供的Reflection A ...

  2. java反射快速入门(二)

    上一遍博文 , 简单介绍java 反射的常用接口,本遍博文, 我会结合项目开发的实际例子讲解下 java反射的使用 现在有个需求, 要将一个对象转换成xml格式, 或者将一串xml转换一个对象, 这时 ...

  3. java 反射类成员_java 反射(二)类成员

    在Java反射的包中定义一个接口java.lang.reflect.Member,它有三个实现类java.lang.reflect.Field, java.lang.reflect.Method, a ...

  4. 夯实Java基础(二十一)——Java反射机制

    1.反射机制概述 Java反射机制是指程序在运行状态中,对于任何一个类,我们都能够知道这个类的所有属性和方法(包括private.protected等).对于任何一个对象,我们都能够对它的属性和方法进 ...

  5. Java安全(二) 反射

    反射相关概念 反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行状态的时候才动态加载类,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的方法 ...

  6. Java反射面试总结(二)

    为什么引入反射概念?反射机制的应用有哪些? 我们来看一下 Oracle 官方文档中对反射的描述: 从 Oracle 官方文档中可以看出,反射主要应用在以下几方面: 反射让开发人员可以通过外部类的全路径 ...

  7. java 获取 反射 方法 名_乐字节Java反射之一:反射概念与获取反射源头Class

    一.Java反射机制概念 "程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言",如Python, Ruby是动态语言:显然C++,Java,C#不是动态语言,但是JAV ...

  8. Java反射(详述版)

    一.什么是反射? 我们先来看一个例子: package venus; public class Student {public String name;public Student(){System. ...

  9. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  10. Java反射机制分析指南

    一.JAVA是动态语言吗? 一般而言,说到动态言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVA和C++一样,都不是动态语言. 但JAVA它却有着一个非常突出的动态相关机制:反 ...

最新文章

  1. 【Xamarin挖墙脚系列:现有IPhone/IPad 设备尺寸】
  2. Sublime-text
  3. python3下载文件-python 3.3 下载固定链接文件并保存的方法
  4. 表贴电阻尺寸与什么有关_PCB板上为什么要“贴黄金”?
  5. 网络QoS的平衡之道——音视频弱网对抗策略介绍
  6. 斯坦福NLP组最新报告:自然语言处理中的学习挑战(附149页报告全文下载
  7. 用计算机表白的数字,用数字表白
  8. 数据库-mysql概述
  9. 转载:word排版之长英文单词自动换行
  10. 「镁客早报」小米“10亿赌约”输给格力;SpaceX本周将首次试飞新飞船...
  11. 看见几篇文章,收藏一下。
  12. LINUX SHELL中大小写转换及注意事项
  13. 维克多DBC文件结构
  14. 计算机右键管理快捷键,鼠标右键菜单管理
  15. 5053刷奥迪Q5隐藏功能
  16. 台式电脑开机显示蓝屏 检查计算机上的病毒,电脑出现蓝屏问题的诊断以及处理的方法...
  17. Python数据类型之三(列表)
  18. 微信退款通知显示乱码,xml解析中文乱码
  19. c语言求出现次数最多的字符,保证你看懂
  20. AWS DynamoDB基础使用

热门文章

  1. apple怎么其他_如何取消您的Apple Music(或任何其他)订阅
  2. document.querySelector()方法
  3. 农户在集市上卖西瓜,他总共有1020个西瓜,第一天卖掉一半多两个,第二天卖掉剩下的一半多两个, 问照此规律实下去,该农户几天能将所有的西瓜卖完。C语言
  4. MapReduce作业提交流程
  5. 谜一样的科学家——阿兰图灵
  6. 公有云上应该怎么做容灾?
  7. 公有云管理的一般建议
  8. 企业上云“行稳致远”,新钛云服“服务+产品”模式升级上云、用云新思维 | 爱分析洞见...
  9. 群体稳定度指标PSI
  10. Shell中的感叹号