的反射特有行为Class.getDeclaredMethods()

小丑:

我有一个抽象类A,B类是扩展A.具体类

除了B级的,但是Java文档调用B.class.getDeclaredMethods()返回Class A的方法签名的说,有些事情就不同 getDeclaredMethods()

“这其中包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。”

因此,从上述文档我期待方法foo(),它是由抽象父类继承不应从回getDeclaredMethods()电话,但我得到方法foo(),它是由抽象父类继承的是从返回getDeclaredMethods()调用。

import java.lang.reflect.*;

public class B extends A {
    public static void main(String[] args) throws Exception {
        Method[] methods = B.class.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println(methods[i]);
        }
    }
}


abstract class A {
    public void foo() {
    }
}

有人可以解释我这种行为。

在这里输入图像描述

欧文Bolwidt:

你这样做的原因是因为超有包级别的访问。如果您更改类的访问修饰符Apublic(你需要把它放在它自己的文件),在额外的方法B.class.getDeclaredMethods()消失。

(还要注意的是,abstract修改后的类A是红鲱鱼:会发生同样的事情时类A不是抽象的)

这是一种解决方法在Java编译器用于反射一个错误:虽然foo是一个公共方法,它在包范围的类定义A你可以反省类B,找到方法,尝试使用反射来调用它,只得到一个IllegalAccessException

编译器将生成一个桥法B,这样就可以正确地反思invoke方法foo


如果你做的方法,这是最好的证明了fooA一个final方法,这使得它不可能解决这个反射错误(这是不可能要覆盖的方法)

AB使用软件包abc和类C是包defC试图反射性invoke方法foo上类B是公共的,但由于它是在非公共类中定义它失败A

异常在线程“主要” java.lang.IllegalAccessException:类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


它的这个错误报告中解释说:

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  }

评估

该提案是增加桥梁的方法在这些极少数情况下,以解决问题的反映,没有其他forseen修订或变通方法。具体而言,当一个公共方法是从非公共类继承到一个公共类,我们会产生一个桥接方法。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章