`

JAVA获取方法参数名的分析(二)

    博客分类:
  • Java
阅读更多

2010年5月13日 魏超

 

上一节:JAVA获取方法参数名的分析(一)

 

javac和Eclipse编译出来的class文件在传入参数名称上的区别

在上文中可以看出,由javac编译的类,IDE在引用了改类的时候,无法获得方法传入参数原来的命名,只能重新赋予arg0,arg1之类的名字。而由eclipse(MyEclipse)编译出来的class文件,却具有传入参数原来的名字。

 

为了能进一步清楚这个区别,我们这里借助一个软件来查看class文件:JClassLib

JClassLib 写道
JClassLib不但是一个字节码阅读器而且还包含一个类库允许开发者读取,修改,写入Java Class文件与字节码。
 

我这里只使用了jclasslib的GUI那个版本。jclasslib作为一个java库还可以有更多更强大的功能。用jclasslib分别打开2个class文件,如下图:


上图可以看出,2个class文件相同的testJar方法下,下面那个testJar方法中还注入了"[1]LocalVariableTable"属性。这个属性通过右边的详细可以看出,存储的就是jarName和yourName2个传入参数的名字。而上面那个javac编译出来的class是没有这个属性的。

对于没有注入参数名称的class,按照我的推断,他应该是根据


上面这个方法中的Descriptor这个标志来判断传入参数是什么类型的,再根据类型给一个默认的名称。

 

注:上图中用红色框起来的descriptor的意思是  <(参数1数据类型,参数2数据类型) 方法返回类型>

 

因此,我们使用Eclipse等IDE在调用spring.jar等jar的方法时,代码提示可以正确读取到传入参数的原命名是因为 spring.jar等jar包在编译时就向class文件注入了参数名字。因此,eclipse等IDE也是通过读取.class的字节码来获得方法的参数名称的。

 

通过网上资料得知,eclipse\myEclipse并没有引用sun默认的javac编译器,而是有自己的实现,因此在编译java文件的时候,由eclipse编译出来的与由javac编译出来的就有所不同。

 

 

Eclipse/MyEclipse中 .class没有注入参数名称的jar在 attach source之后的区别

上一节的分析,我们了解到,倘若在生成.class文件的时候没有注入参数名称的信息,那么在引入这个class之后,使用它类的方法时,代码提示的参数就只会是arg0,arg1之类的名称。但当我们对这个引入的jar包进行了  attach source之后,代码提示的时候就可以按照source中的正确参数名称来显示。

是不是attach source之后,IDE向jar包中写入了参数名称的信息?

用jclasslib打开attach source以后的class.可以发现这个.class没有发生变化。那么还有一种可能性,就是进行了这个操作之后,eclipse再进行代码提示的时候,是直接从source中读取参数名称的。为了验证这点,我们修改source中方法的参数名。将jarName改成jarNameTest. 再次使用代码提示,可以看到,原来的参数名字没有发生变化。因此,IDE并没有每次都从sourc中读取参数的名称。而是在attach的时候读取了一次,之后做了缓存。

 

看到这里,我的第一个反应是eclipse在这个工程的目录下保存了类似“索引”的东西,将方法参数对应的名称保存了下来。针对这个猜测,我监测了attach前后的工程目录情况,如下图:



 发生变化的只有.classpath文件。source的路径被写到了这个文件中。因此,IDE并没有建立索引。那么可以猜测,eclipse可能在内存中做了缓存,也可能是在自己的公共目录下建立了索引。

 

对于在内存中缓存的可能,我们只要杀死eclipse的进程便可以验证(重启eclipse).结果发现,参数名称变成了修改后的。那么可以看出,这个参数名称的缓存,eclipse是放在自己开辟的一块内存空间内的,只是临时的。在失去了这个缓存之后就会重新读取。

 

 

小结

通过上面的分析,我们可以得出一个结论,eclipse等IDE在代码提示时对方法参数名称的获取,有2种途径。

A.当.class文件中持有 参数名称 信息的时候,会直接从class中读取。

B.当没有时,从.java源文件中,通过字节流读取参数名称,然后缓存起来。

 

因此,我们要模仿IDE的做法,获得一个方法的传入参数名称,我们有上面2种途径。具体的实现,在下一篇心得里会继续分析。

  • 大小: 96.4 KB
  • 大小: 35.2 KB
  • 大小: 52.4 KB
分享到:
评论
4 楼 ocaicai 2013-12-13  
https://gist.github.com/wendal/2011728#file-methodparamnamesscaner-java
3 楼 ta8210 2010-11-11  
我这里有2种办法供你选择
1.使用javassist.jar 这个项目可以帮助你解决这个问题,它是一个增强的反射工具。
项目地址http://www.csg.is.titech.ac.jp/~chiba/javassist/
使用例子http://www.blogjava.net/Hafeyang/archive/2010/10/25/using_powerful_java_reflect_tool_javassist_to_getParameterAnnotations_and_getParameterNames.html
但是这个工具的运行效率没有ASM高。

你也可以使用ASM来扫描Class文件这样获取你要的属性名,前提是你需要对 Class字节码有比较深入的了解。

我更趋向于使用后者,但是ASM的API没有javassist方便。
2 楼 javaest 2010-07-09  
还要说一句,很期待你的本系列的第三篇文章.
1 楼 javaest 2010-07-09  
是个细心人 ,是一片好文章.
我也关注这个问题.
在我的Web框架中,我需要根据参数名称自动到Request中的parameter中取得参数值.
最后没办法我在每个参数上加了标注信息解决这个问题.
你也可以借鉴一下.

    public JSONObject updateFunctionMenuTree(@Para("moduleId") String moduleId ,@Para("roleIdCommaStrForMenu") String roleIdCommaStr,@Para("state") String state) {
        System.out.println(state);
        List<String> menuIdList=menuAndFunctionDao.getAllMenuId(moduleId);
        String[] roleIdArr=roleIdCommaStr.split(",");
        System.out.println(roleIdArr.length);
        int addItemCount=0;
        for (int i = 0; i < roleIdArr.length; i++) {
            addItemCount=securityManager.tempAddSecurityMenuIdForRole(roleIdArr[i], menuIdList);
        }        
        consoleTreeMenuBuilder.reloadTreeMenu(moduleId);
        JSONObject object=new JSONObject();
        object.put("msg", "成功更新功能菜单树 ! "+(addItemCount==0?"":"\n并为选中角色临时添加了 "+addItemCount+" 项菜单的操作权限 ! "));
        return object;
    }


在JAVA 7.0 中,编译时就不会丢掉参数名称信息了.据说.这个说法源于:http://www.ibm.com/developerworks/cn/java/j-javaroundtable/index.html

相关推荐

    java获取apk的包名版本信息

    在Java编程环境中,获取APK文件的包名和版本信息是一项常见的需求,特别是在自动化测试、应用管理或数据分析等场景中。APK是Android应用程序的安装包,它包含了应用的所有组件和资源。要从APK文件中提取这些元数据,...

    java反射,获取所有属性、方法以及List集合类

    在Java中,反射主要用于在运行时分析类和对象,包括访问私有成员、调用私有方法、创建对象、获取类信息等。本篇文章将深入探讨如何使用Java反射来获取一个类的所有属性、方法,并处理List集合类。 首先,让我们了解...

    java反射获取所有属性,获取所有get方法,包括子类父类

    在Java中,反射主要用于在运行时分析类和对象,包括访问私有成员、调用私有方法、创建动态代理等。在标题和描述中提到的知识点主要集中在如何通过反射获取类的所有属性和get方法,包括来自子类和父类的。下面将详细...

    java实现根据方法查看方法参数名称

    3. 使用反射和调试信息:如果程序是在可调试环境中运行,我们可以利用Java的反射API结合调试信息来获取参数名称。`java.lang.reflect.Method`的`getGenericParameterTypes()`可以获取参数类型,但不是名称。为了获取...

    java 获取apk包名和版本号

    这里使用了`getPackageManager()`方法获取到设备上的包管理器,然后通过`getPackageInfo()`方法传入包名和参数,得到`PackageInfo`对象,其中包含了版本名称和版本代码。 在“ReadApk”项目中,你可能会看到一个...

    Java 获取区域号段

    在Java编程中,获取区域号段通常涉及到对电话号码、邮政编码或地理位置的处理。这在开发各种应用,如通信服务、地理位置跟踪或数据分析时非常有用。标题“Java 获取区域号段”暗示了我们可能在讨论如何使用Java来...

    java filter打印请求返回参数

    ### Java Filter 打印请求返回参数详解 #### 一、背景与目的 在Web开发过程中,经常需要在请求处理流程中增加一些通用的功能,比如日志记录、性能监控、安全控制等。Java Servlet规范提供了Filter机制来实现这些...

    java 请求参数过滤拦截

    在Java开发中,请求参数过滤拦截是一个至关重要的环节,它涉及到系统的安全性、稳定性和数据的正确性。这里的“java请求参数过滤拦截”主要是指在接口接收到用户输入的数据时,通过过滤器(Filter)对参数进行检查,...

    java ipmi,vxipmi 通过java获取服务器信息,温度、风扇、内存等

    Java程序需要正确配置这些认证参数以确保安全连接。 3. **查询传感器数据**:IPMI定义了一系列传感器类型,如温度传感器、电源状态、风扇速度等。使用VxIPMI库,你可以调用特定方法获取这些传感器的数据。例如,`...

    java 获取当前时间

    ### 二、具体代码示例分析 #### 1. 创建Date对象 ```java Date now = new Date(); ``` 这里创建了一个`Date`对象`now`,它表示当前系统时间。 #### 2. 使用`DateFormat`格式化时间 - **默认格式化样式**: ```...

    Java获取自身运行相关信息.rar

    "Java获取自身运行相关信息"的主题涵盖了如何使用Java内置的类和方法来获取关于Java虚拟机(JVM)以及相关系统属性的详细信息。下面将详细介绍这些知识点: 1. **Java虚拟机名(JVM Name)**: 通过`java.lang....

    Java获取MQ连接数的Demo.zip

    接下来,我们可以分析`Java获取MQ连接数的Demo.java`代码。在这个示例中,开发者可能创建了一个名为`RabbitMQConnectionCount`的类,该类包含一个方法,如`getRabbitMQConnectionCount()`,用于获取RabbitMQ的当前...

    ASM函数监听实现(二)之打印注入函数的参数值

    这篇博客"ASM函数监听实现(二)之打印注入函数的参数值"深入探讨了如何利用ASM库来监控并记录函数调用时的参数值,这对于调试、日志记录以及性能分析等场景非常有用。 首先,我们来看`asmAopClassAdapter.java`。...

    java对音频文件的频谱分析

    1. `ldlib.jar`、`kj_dsp.jar`、`ldsa.jar`:这些都是Java库文件,可能包含了用于音频处理和频谱分析的类和方法。例如,`ldsa.jar`可能包含了频谱分析算法的实现,而`kj_dsp.jar`可能提供了数字信号处理的功能,如...

    java获取天气预报

    第二种方法是分析中央气象台页面源码,通过HTMLUnit技术从HTML中抓取实时天气信息。HTMLUnit是一个无头JavaScript浏览器,它可以模拟浏览器行为,加载并执行网页上的JavaScript代码。这对于获取动态加载的天气信息...

    Java获取凌晨时间戳的方法分析

    Java获取凌晨时间戳的方法分析 Java获取凌晨时间戳是Java编程中的一项基本操作,通常用于记录用户行为、日志记录、数据统计等场景中。下面我们将详细介绍Java获取凌晨时间戳的两种方法,并对比分析它们的优缺点。 ...

    java反射基本方法测试

    在Java中,反射主要用于在运行时分析类、接口、字段和方法的信息,使得我们可以在不知道对象具体类型的情况下创建和操作对象。下面我们将详细探讨Java反射的基本方法及其应用。 一、获取类信息 1. `Class` 类:...

    java获取视频信息,帧(封面图片)

    总之,Java调用FFmpeg进行视频信息获取和帧提取是一项实用的技术,可以为多媒体应用如视频编辑、分析或信息检索等场景提供便利。通过熟悉FFmpeg命令和相应的Java库,开发者可以高效地实现这些功能。

    天气预报数据获取java代码(风和天气、高德地图)

    你需要读取这个Excel文件,使用Java的Apache POI库或者JExcelApi来解析,获取到对应地区的编码,然后用这些编码作为查询参数。 4. **高德地图API集成** 高德地图的天气API可能需要用户的位置信息,因此可能需要...

    javacore分析工具

    解压后阅读,可以了解如何使用这个JavaCore分析工具,以及可能遇到的问题和解决方法。 至于`license`文件,它包含了软件的许可协议,规定了用户可以如何使用、分发和修改这个工具。确保遵循这些条款是非常重要的,...

Global site tag (gtag.js) - Google Analytics