您获得此内容的原因是因为超类具有包级别访问权限。如果将 class 的访问修饰符更改为(需要将其放在其自己的文件中),则 中的额外方法将消失。A
public
B.class.getDeclaredMethods()
(另请注意,修改后的类是一条红鲱鱼:当类不是抽象时,也会发生同样的事情)abstract
A
A
这是Java编译器中针对反射错误的替代方法:尽管它是一个公共方法,但它是在包作用域类中定义的。你可以反思类,找到方法,尝试使用反射调用它,只是为了得到一个.foo
A
B
IllegalAccessException
编译器将在类中生成一个桥接方法,以便您可以正确地反射调用方法。B
foo
如果你在方法中制作方法,这最好地证明,这使得无法修复这个反射错误(不可能重写该方法)foo
A
final
类 和 在包中,类在 包 中。类尝试在公共类上反射性地调用方法,但它失败了,因为它是在非公共类中定义的。A
B
abc
C
def
C
foo
B
A
线程 “main” java.lang.IllegalAccessException 中的异常: Class def.C 无法访问类 abc 的成员。带有修饰符“公开最终”的 A
package abc;
public class B extends A {
}
class A {
public final void foo() {
}
}
package def;
import java.lang.reflect.Method;
import abc.B;
public class C {
public static void main(String[] args) throws Exception {
Method m = B.class.getMethod("foo");
m.invoke(new B());
}
}
只需从方法中删除关键字即可解决此问题,因为编译器随后会在类 中插入合成桥接方法。final
foo
B
此 bug 报告中对此进行了解释:
http://bugs.java.com/view_bug.do?bug_id=6342411
描述
下面的程序在运行时失败,并出现此错误:
Exception in thread "main" java.lang.IllegalAccessException: Class refl.ClientTest can not access a member of class refl.a.Base with
modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Method.invoke(Method.java:578)
at refl.ClientTest.main(ClientTest.java:9)
========== test/refl/a/Base.java ==========
1 package refl.a;
2
3 class Base {
4 public void f() {
5 System.out.println("Hello, world!");
6 }
7 }
========== test/refl/a/Pub.java ==========
1 package refl.a;
2
3 public class Pub extends Base {}
========== test/refl/ClientTest.java ==========
1 package refl;
2 import refl.a.*;
3 import java.lang.reflect.*;
4
5 public class ClientTest {
6 public static void main(String[] args) throws Exception {
7 Pub p = new Pub();
8 Method m = Pub.class.getMethod("f");
9 m.invoke(p);
10 }
11 }
评估
建议在这些非常罕见的情况下添加桥接方法,以修复反射中的问题,而无需其他可预见的修复或解决方法。具体来说,当公共方法从非公共类继承到公共类时,我们将生成一个桥接方法。