随笔-193  评论-715  文章-1  trackbacks-0
今天调试别人写的程序的时候,发现总出NoSuchMethodException,经过一翻跟踪,原来是getDeclaredMethod() 中报出来的,遂进行一翻调查:

假设我有两个类,TestB继承TestA,如下:
public class TestA {
    
public void tt() {
    }

}

public class TestB extends TestA {
    
public void aaa() {
    }

}
另有一个带main方法的主程序:
import java.lang.reflect.Method;

public class Test {

    
public static void main(String[] args) {
        
try {
            TestB b
=new TestB();
            Method m 
= b.getClass().getDeclaredMethod("tt"new Class []{});
            System.out.println(m);
        }
 catch (Exception e) {
            e.printStackTrace();
        }

    }


}

这个程序就会抛出如下异常:
java.lang.NoSuchMethodException: TestB.tt()
    at java.lang.Class.getDeclaredMethod(Class.java:
1937)
    at Test.main(Test.java:
8)

给我直观的感觉就是不能反射父类中的方法,但是为什么了?JDK的文档里也没有写说不行呀?
getDeclaredMethod
public Method getDeclaredMethod(String name,
                                Class parameterTypes)
                         
throws NoSuchMethodException,
                                SecurityException返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。name 参数是一个 String,它指定所需方法的简称,parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形式参数类型。如果在某个类中声明了带有相同参数类型的多个方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则返回该方法;否则将从中任选一个方法。如果名称是 
"<init>” 或 “<clinit>",则引发一个 NoSuchMethodException。 

参数:
name 
- 方法名
parameterTypes 
- 参数数组 
返回:
该类与指定名和参数相匹配的方法的 Method 对象 
抛出: 
NoSuchMethodException 
- 如果找不到匹配的方法。 
NullPointerException 
- 如果 name 为 null 
SecurityException 
- 如果存在安全管理器 s,并满足下列任一条件: 
调用 s.checkMemberAccess(
this, Member.DECLARED) 拒绝访问已声明方法 
调用方的类加载器不同于也不是该类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 
从以下版本开始: 
JDK1.
1 

这是为什么了?用javap来看看字节码:执行javap -c TestA 得到如下结果:
Compiled from "TestA.java"
public class TestA extends java.lang.Object{
public TestA();
  Code:
   
0:   aload_0
   
1:   invokespecial   #8//Method java/lang/Object."<init>":()V
   4:   return

public void tt();
  Code:
   
0:   return

}

再执行javap -c TestB
Compiled from "TestB.java"
public class TestB extends TestA{
public TestB();
  Code:
   
0:   aload_0
   
1:   invokespecial   #8//Method TestA."<init>":()V
   4:   return

public void aaa();
  Code:
   
0:   return

}

原来如此,在TestB的字节码中,我们无法找到TestA中定义的tt()方法。我想这就是为什么了。
posted on 2010-08-12 14:48 Robin's Programming World 阅读(2355) 评论(3)  编辑  收藏 所属分类: Java

评论:
# re: Investigate getDeclaredMethod of Java Reflection 2010-08-12 16:39 | 路人
。。。
使用getMethod()就好了,获取所有公开的方法,包括父类的。  回复  更多评论
  
# re: Investigate getDeclaredMethod of Java Reflection 2010-08-12 17:00 | Robin's Java World
@路人
有个问题:我只想要指定的那一个,或许可以通过方法名来循环,但如果这个方法是重载的了?
  回复  更多评论
  
# re: Investigate getDeclaredMethod of Java Reflection 2010-08-13 15:35 | 狄浩
...当年写底层公用方法时候是用try(){}catch(){}反复回调自身函数来解决这个问题,现在算是知道什么原因了  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: