在使用java的reflection时(java 1.5环境),遇到一些与自己直观的想法有差别的使用方式,这背后或许隐藏着深思熟虑的设计理念,又或者较为无奈的受到实现的约束,手头暂时没有时间去深究探讨,先罗列下来以备今后查阅:
1. 方法参数不能含有基本类型
如我们不能有 aObj.getClass().getMethod(methodName, int) 的用法
这也就决定了aObj的类中不能有 methodName(int) 这样的方法
解决方法是用对应的包装类,如Integer,这在使用上不是很美观,这样设计猜测应该是实现的限制
2. 方法的访问权限必须是public
这个限制的设计理念还是很好理解的,因为我们一般使用反射的情况应该是在框架中,而框架代码与应用代码往往是由不同的机构提供。
但在我使用时遇到了一点小小的郁闷,我有一个类的功能是根据配置信息决定什么时候调用自己的哪一个方法,这些方法只在内部用到理应不给public的访问权限,再不济也是protected,不知道jvm有没有能力在使用反射时动态的检查访问权限的问题。(如果没有记错现在应该是编译时验证)
3. 反射与继承
还是1中的getMethod方法,只是主角不再是基本类型,而换成基类与子类。
如 aObj.getClass().getMethod(methodName, anArrayList.getClass()) 会在aObj的类中寻找参数类型(这里anArrayList是ArrayList<String>的实例)完全匹配的方法。
即便aObj的类中有一个方法 methodName(List<String>) ,getMethod也会认为不是它所想要的方法。这让我很纳闷,难道不鼓励使用反射的地方采用基于接口的编程么?
4. 反射与泛型
接3中的例子,我原本的getMethod写法是这样的:
aObj.getClass().getMethod(methodName, List<String>.class)
但编译器告诉我它不允许这么写,几经尝试后发现用 List.class 就可以了,这似乎限制了aObj的类methodName方法的重载,因为List<String>, List<Integer>, List<Double>等都被认为是List.class。猜测或许是java升级到1.5引入泛型后与其它特性需要一个逐渐融合的过程吧。