- 浏览: 322741 次
- 性别:
- 来自: 福建
文章分类
最新评论
-
wangyonglin1123:
完美解决 谢谢您
BufferedReader中文乱码解决 -
wangyonglin1123:
StringBuilder result = new Stri ...
BufferedReader中文乱码解决 -
u011110982:
楼主,代码呢?
PKI体系简易JAVA实现(一):时间戳服务器TSA -
WangSongYuan:
我也遇到楼主一样的问题 果然在<body>后面填一 ...
Extjs IE8 对象不支持此属性或方法的bug -
ocaicai:
https://gist.github.com/wendal/ ...
JAVA获取方法参数名的分析(二)
2010-5-12 魏超
关于题目
首先解释一下题目. 我们知道, Java通过反射,可以从一个类得知它有哪些方法,有哪些变量,也可以知道每个方法中有哪几个什么类型的传入参数。但有一个东西反射取不到,那就是我们对方法传入参数的命名。
取得传入参数的名字有什么意义?
对这个问题的探究,源于在写一个测试类时候的需求。假设我们有一个类需要测试,这个类中有数十个方法。为每个方法编写测试类,将耗费大量的时间和精力。因此我有一种想法,就是通过java的反射,获得这个类所有的方法,再通过传入参数的名字和参数类型,来生成一些符合要求的数据进行传入。(能这样生成数据的前提是:这个类的编码需要遵循严格的规范,对参数的命名有统一的标准,同时,这个类应该和某种业务紧密相关,这样,才能通过业务和参数名字,判断应生成什么合适的数据)。如果能做到上面说的,那么对具有数十或数百个方法的类,要测试的话只需要传入这个类就可以了。
存在的问题
根据上面的设想,问题就出现了。获得类的方法,获得类的参数类型,反射都可以做到。但参数名称呢?上网求证,多数人给了直接否定的答案。因为API中根本没有提供相关的方法。但有一些人的观点启发了我。他们提到,IDE(如eclipse,myeclipse)中在编码过程中,调用一个类的方法,在代码提示的时候,ide是可以显示出方法中的参数名字的,如下图:
IDE是怎样做到的呢,如果IDE可以做到,我们是否可以尝试去分析它们的做法,来获得参数名称。
可能的做法
网上找到了一个很直观的方法——通过直接读取.java文件,把类作为一个普通文本,用正则表达式匹配方法,来直接获取参数的名字。
/** * @author zhangc * *一个测试程序,用来扫描文件(java文件),找出所有方法的参数列表 */ import java.io.*; import java.util.regex.*; public class ScanSource { static void findArgsList(Object targetSrc) { /* * 正则匹配串基本上是这样子分组情况(A(B(c(d)))) * 串是:(\\w+\\s+\\w+\\s*\\(((\\s*\\w+\\s*(\\[ * \\])*\\s*\\s+(\\[\\])*\\s*\\w+\\s*(\\[\\])*,?)+)\\)\\s*\\{) 比如public * static void findArgsList(Object targetSrc,int []a){ * A是匹配整个方法定义行:这里是:static void findArgsList(Object targetSrc,int []a){ * B是匹配匹配参数列表:这里是Object targetSrc,int []a * C是匹配一个参数,包括类型和类型名称和逗号:这里是Object targetSrc, D是匹配数组标识符:这里是[] * 这个串有点bt,水平有限,只能这样 */ Pattern p = Pattern .compile("(\\w+\\s+\\w+\\s*\\(((\\s*\\w+\\s*(\\[\\])*\\s*\\s+(\\[\\])*\\s*\\w+\\s*(\\[\\])*,?)+)\\)\\s*\\{)"); Matcher m = p.matcher((CharSequence) targetSrc); // locate the all methord defination while (m.find()) { String methodName = m.group(0); String methodArgName = m.group(1); String strArgs = m.group(2); String fourArgs = m.group(3); System.out.println(methodName + "\n" + methodArgName + "\n" + strArgs + "\n" + fourArgs + "\n"); } } public static String LoadTargetFile(String targetFileName) { String result = null; try { FileInputStream fis = new FileInputStream(targetFileName); // 临时分配10000size给byte数组。 byte[] bufReceived = new byte[10000]; int counts = fis.read(bufReceived); byte[] bufActual = new byte[counts]; System.arraycopy(bufReceived, 0, bufActual, 0, counts); result = new String(bufActual); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; } public static void main(String[] args) { String target = LoadTargetFile("src/com/spring/aop/TestAspect.java"); System.out.println(target); findArgsList(target); } }
这个通过正则表达式的类,在我写的一个简单的测试类中,是可以取得参数的值的,但当把它用在我们那个有几十个方法的类的时候,表达式的匹配就失效了,没有得到任何的结果(具体原因可能是正则表达式的错误,没能匹配到一些方法)。同时,这种方法需要有.java这个源文件,而在IDE中引入的常常是.class组成的Jar包。为了进一步了解IDE对方法传入参数名的处理,下面我做了一个测试。
测试IDE对方法传入参数的处理
建立一个工程。在工程中新建如下的一个类:
package testplugin; public class TestJar { public void testJar(String jarName, String yourName){ System.out.println("jarName:" + jarName + "|| yourName:" + yourName); } }
接着我们用2种方式对这个类打jar包:
1. 用javac编译类文件然后打到jar包中,命名为testPlugin_javac.jar.
2. 用MyEclipse直接对工程进行导出,导出为testPlugin_myeclipse.jar.
(打开2个jar中的TestJar.class文件,会发现2个class文件有差异)。
再建立一个工程,先后将2个jar包引入做实验,可以看到:
1. 引入testPlugin_javac.jar, 调用testJar方法,如下图
可以看到,2个传入参数失去了原有的名称。
2. 移除上面的包,引入testPlugin_myEclipse.jar, 调用testJar方法,如下图
可以看到,参数名称被识别出来了。
关键在于,2个jar包中的class文件不同。我们打开2个class文件(我们只是直观的看一下class文件中的变量,所以没有用专用的工具查看):
javac生成的.class:
myelipse直接打出来的.class(实际上就是调用了debug模式编译出来的.class):
2个class文件里下面的部分都有SourceFile块。应该是用来表示这个class文件是从哪个java文件编译来的。我们重点看上面的部分。
可以看到,用普通的javac编译出来的类,方法的传入参数名会被编译器修改,于是上面第一个图里SourceFile以上的部分就找不到jarName和yourName 2个名字。而只有通过-debug模式编译出来的类,它的参数名才能被保存下来。而也就是在.class文件中有保留下来参数名的jar包,在IDE中代码提示才能正确显示出参数名字。
那么说明IDE是否能识别类中的方法名取决于编译过后产生的不同的class文件。那么下一节我们会使用工具来解析这2个class文件来看其中到底有什么不同。
发表评论
-
JVM 垃圾回收机制与GC性能调优
2011-11-14 10:00 1267一篇还不错的分析。网上可查到很多转载,原文系谁所作已不可 ... -
事务相关总结记录
2011-09-21 16:35 1275查问题过程中,仅对一些东西做下记载。 在总体事务结束前 ... -
JAVA远程调试tomcat、WebSphere
2011-08-04 11:35 5913习惯于直接在eclipse里对 ... -
Ubuntu11.04Server64安装websphere mq 64位
2011-07-18 15:07 2754环境: Ubuntu-11.04-Server-64位 ... -
《Java Collections Framework》文摘及总结
2011-07-11 18:32 01. * The Collection interfa ... -
Maven eclipse debug
2011-04-12 15:24 1083mvn -Dwtpversion=2.0 eclipse:ec ... -
for和Iterator比较
2011-01-21 13:05 1810小记: 2种方式的速度和被操作数据集的类型有关系。 ... -
Appfuse所加载的jar包的作用
2010-06-30 10:50 0最近想深入学习下Appfuse框架。从官网上下了一个Sprin ... -
Ant propertyregex无返回值的问题
2010-05-31 15:58 4271<propertyregex property=&quo ... -
JAVA获取方法参数名的分析(二)
2010-05-13 14:29 80072010年5月13日 魏超 上一节:JAVA获取方法参 ... -
spring配置文件中对bean的id和name设置的区别
2010-05-11 10:32 1970我一直认为spirng的bean只能配置一个Id. 事实上,b ... -
关于子类和父类实现同一个接口
2010-05-04 11:20 5263这个问题是由下面的代码引出的: public c ... -
轻量级缓存 EhCache 简介
2010-04-26 10:29 1649转载自:http://blog.csdn.net/teed ... -
使用statCVS
2010-01-12 16:04 1525现在的项目里用CVS做版 ... -
Collection和Collections的区别
2009-10-19 16:37 1433Collection是个java.util下的接口,它是各种集 ... -
sleep和wait的区别
2009-10-19 16:34 61521、这两个方法来自不同的类分别是Thread和Object ... -
Apache、Tomcat、JBoss、WebLogic的区别与关系
2009-10-19 16:20 10960Apache全球应用最广泛的http服务器,免费,出自ap ... -
BufferedReader中文乱码解决
2009-10-15 11:00 70456做一个从windows cmd截获命令返回值的java程序,结 ... -
Swing Synth外观定制UI
2009-10-14 13:44 1806本文将深入透视 Synth 外 ... -
Eclipse 中警告:不能读取 AppletViewer 的属性文件解决
2009-10-14 10:18 2478警告:不能读取 AppletViewer 的属性文件: C:\ ...
相关推荐
在Java编程中,有时我们需要获取一个方法的参数名称,这对于日志记录、调试或动态代码生成等场景非常有用。然而,Java的常规运行时API并不直接提供这样的功能,因为参数名称在编译后的字节码中通常是不可见的。本文...
在Java编程环境中,获取APK文件的包名和版本信息是一项常见的需求,特别是在自动化测试、应用管理或数据分析等场景中。APK是Android应用程序的安装包,它包含了应用的所有组件和资源。要从APK文件中提取这些元数据,...
在Java中,反射主要用于在运行时分析类和对象,包括访问私有成员、调用私有方法、创建对象、获取类信息等。本篇文章将深入探讨如何使用Java反射来获取一个类的所有属性、方法,并处理List集合类。 首先,让我们了解...
在Java开发中,请求参数过滤拦截是一个至关重要的环节,它涉及到系统的安全性、稳定性和数据的正确性。这里的“java请求参数过滤拦截”主要是指在接口接收到用户输入的数据时,通过过滤器(Filter)对参数进行检查,...
### Java Filter 打印请求返回参数详解 #### 一、背景与目的 在Web开发过程中,经常需要在请求处理流程中增加一些通用的功能,比如日志记录、性能监控、安全控制等。Java Servlet规范提供了Filter机制来实现这些...
在Java中,反射主要用于在运行时分析类和对象,包括访问私有成员、调用私有方法、创建动态代理等。在标题和描述中提到的知识点主要集中在如何通过反射获取类的所有属性和get方法,包括来自子类和父类的。下面将详细...
JavaCore分析工具是一种在Java应用程序出现问题时,如CPU占用过高或出现Out Of Memory (OOT)错误时,用于诊断和分析的利器。它主要用于Java虚拟机(JVM)的故障排查,尤其是在使用像Websphere或Weblogic这样的企业级...
在Java编程环境中,进行音频文件的频谱分析是一项复杂但重要的任务,特别是在音频处理和音乐信息检索领域。本文将深入探讨如何使用给定的压缩包文件来实现这一目标。 首先,频谱分析是将时域信号转换为频域表示的...
在Java编程语言中,捕获控制台的输出信息是一个常见的需求,尤其是在进行单元测试或调试时,需要收集程序运行过程中的标准输出以便于分析。在提供的代码片段中,展示了一种通过重定向`System.out`流来实现这一目标的...
总结,这个“ReadApk”项目提供了一种在Java环境中获取APK包名和版本号的方法,无论是从已安装的应用还是未安装的APK文件。这对于自动化测试、应用市场分析或者自定义应用管理工具都有一定的实用价值。通过深入理解...
在Java中,反射主要用于在运行时分析类、接口、字段和方法的信息,使得我们可以在不知道对象具体类型的情况下创建和操作对象。下面我们将详细探讨Java反射的基本方法及其应用。 一、获取类信息 1. `Class` 类:...
`asmAopGenerator`可能负责生成一个代理类,这个代理类在调用目标方法之前和之后,会执行自定义的代码,比如获取并打印参数值。 `helloWorld.java`可能是测试用例,包含了一个简单的函数调用来展示ASM的监听功能。...
- 使用合适的JVM调优参数,比如设置合理的堆大小,启用垃圾收集日志,以帮助分析工具获取更全面的信息。 - 学习和理解JVM内存模型,包括堆、栈、方法区等,有助于更好地分析内存问题。 6. **标签解析**: - "jvm...
Java方法签名包括返回类型、方法名和参数类型,例如,`public int add(int, int)`。 在JNI中,Java方法签名被转换为一种特殊的格式,称为JNI方法签名。例如,上述Java方法`add`的JNI方法签名会是`"(II)I"`。这里的...
在压缩包中只有一个名为“jar”的文件,这很可能是一个Java的JAR(Java Archive)文件,里面可能包含了实现上述功能的Java类和资源。通常,JAR文件是Java应用程序或库的打包形式,可以通过Java的`jar`命令或IDE(如...
例如,创建服务区分析对象、设置分析参数、执行分析任务和获取分析结果等步骤。同时,“serviceArea”文件可能包含的是分析后的结果数据或者示例的输入数据。 在进行服务区分析时,还需要注意以下几点: 1. 数据...
Java提供了一个名为Java Device Control API(JavaDCP)的接口,允许开发者访问和控制硬件设备,包括摄像头。然而,JavaDCP并不是标准的Java库,因此在实际项目中,我们通常会依赖第三方库,如Java Media Framework ...
总之,Java调用FFmpeg进行视频信息获取和帧提取是一项实用的技术,可以为多媒体应用如视频编辑、分析或信息检索等场景提供便利。通过熟悉FFmpeg命令和相应的Java库,开发者可以高效地实现这些功能。
这个"java 根据参数导出txt文件.rar"压缩包文件可能包含了一个名为"EXTtest.java"的源代码文件,该文件展示了如何在Java中根据特定参数生成TXT文本文件。下面将详细讨论相关的知识点: 1. **文件I/O操作**:在Java...