使用反射调用匿名内部类时应该注意的一些地方
2015-12-11 17:05
519 查看
06年写的
在使用匿名内部类时,当使用了反射机制来调用其中的方法就会出现访问异常,这是在前几天写程序时遇到的,所以在写匿名内部类时一定要注意是否在其它地方使用了反射调用。下面给出部份代码来说明此问题。
上面的代码看似很简单运行时一般都不会有什么错误出现,但是如果将类Test与Exec放在不同包的时候,就会出现异常。因为Exec类无法调用Test中匿名内部类的hello方法导致异常,也许到这里大家都觉得容易理解,但为什么在注释1的地方可以通过,在注释2的地方就会出异常呢?这个问题就会使许多朋友开始疑惑了。下面针对该部份内容进行讨论学习。
根据匿名内部类的定义,我们知道:
的意思是产生一个匿名的class对象,此匿名class继承自SuperTest类,new后返回一个SuperTest类型的对象。那么为什么注释2的地方会出异常呢,我们仔细想一下匿名内部类的定义就很清楚了,上面这段代码可以等同于下面:
这样就很容易理解了,在注释2的地方使用了target.getClass(),而它得到的Class就是MySuperTest,但是此类的修饰符是default的,也就是说在其它包是不能访问的,所以使用此方法进行调用时会出现异常。虽然容易理解,但开发时经常不注意,常出现类似的问题。
解决方法当然也是有多种的,呵呵,如果将class MySuperTest加上public修饰符,可以解决此问题,但这样就不能再使用匿名内部类了,所以也可以将Exec类进行修改,就是在注释2的地方获取对象的父类,然后再调用,这样就可以使用这种结构(但需注意,获取父类时一定要先判断是否有所要调用的方法,因为有的并不包含此方法)。
在使用匿名内部类时,当使用了反射机制来调用其中的方法就会出现访问异常,这是在前几天写程序时遇到的,所以在写匿名内部类时一定要注意是否在其它地方使用了反射调用。下面给出部份代码来说明此问题。
public class SuperTest { public void hello() { System.out.println("Hello from SuperTest"); } } public class Exec { public static void run(SuperTest target) { System.out.println(); System.out.print("base class > "); run(target, SuperTest.class, "hello"); //1 这里可以正常执行 System.out.print("obj class > "); run(target, target.getClass(), "hello"); //2 这里可能产生异常 } static void run(Test1 target, Class cls, String method) { try { cls.getMethod(method, null).invoke(target, null); } catch (Exception x) { System.out.println(x); } } } public class Test { public static void main(String[] args) { Exec.run(new SuperTest() { public void hello() { System.out.println("Hello from Test"); } }); } }
上面的代码看似很简单运行时一般都不会有什么错误出现,但是如果将类Test与Exec放在不同包的时候,就会出现异常。因为Exec类无法调用Test中匿名内部类的hello方法导致异常,也许到这里大家都觉得容易理解,但为什么在注释1的地方可以通过,在注释2的地方就会出异常呢?这个问题就会使许多朋友开始疑惑了。下面针对该部份内容进行讨论学习。
根据匿名内部类的定义,我们知道:
Exec.run(new SuperTest() { public void hello() { System.out.println("Hello from Test"); } });
的意思是产生一个匿名的class对象,此匿名class继承自SuperTest类,new后返回一个SuperTest类型的对象。那么为什么注释2的地方会出异常呢,我们仔细想一下匿名内部类的定义就很清楚了,上面这段代码可以等同于下面:
Exec.run(new Test().new MySuperTest()); class MySuperTest extends SuperTest { public void hello() { System.out.println("Hello from Test"); } }
这样就很容易理解了,在注释2的地方使用了target.getClass(),而它得到的Class就是MySuperTest,但是此类的修饰符是default的,也就是说在其它包是不能访问的,所以使用此方法进行调用时会出现异常。虽然容易理解,但开发时经常不注意,常出现类似的问题。
解决方法当然也是有多种的,呵呵,如果将class MySuperTest加上public修饰符,可以解决此问题,但这样就不能再使用匿名内部类了,所以也可以将Exec类进行修改,就是在注释2的地方获取对象的父类,然后再调用,这样就可以使用这种结构(但需注意,获取父类时一定要先判断是否有所要调用的方法,因为有的并不包含此方法)。
相关文章推荐
- C++函数指针
- 清除行列(程序员面试金典)
- ubutu下链接手机后 ,安装软件到手机 ----针对开发者
- 机器手臂(1):研究舵机固定支架
- orcal集群导入dmp文件
- ssh传输本地文件
- Autofac创建实例的方法总结
- 企业级工程输出log4j学习
- [ WARN ] Keyword 'Capture Page Screenshot' could not be runon failure: No browser isopen
- 1118有限自动机的构造与识别
- 进程与线程的一个简单解释(转)
- fread,read,fscanf,fput
- 微信开发笔记
- Mac下的常识操作
- Qt编程风格指南及命名约定
- js
- Linux下查看文件常用命令-cat,more,less,head,tail
- C语言学习总结(四) 剩余内容
- CSS3.0盒模型display:flex;的使用[兼容微信浏览器]
- SQL server 时间处理自连接