0

默认情况下匿名内部类是私有的吗?我可以将它们公开吗?

我需要通过反射访问方法。

4

4 回答 4

7

匿名内部类之所以匿名是有原因的:它们并不意味着可以直接从外部世界访问,只能通过引用变量/方法参数来访问。(出于同样的原因,它们也是私有的。)

我猜您可能会尝试使用编译器生成的名称(例如OuterClass$1)通过反射访问这样的类,但是这是特定于实现的,并且可能会在您将另一个匿名内部类添加到同一个外部类或在下一个 JVM 版本中更改. 所以这样的解决方案将非常脆弱。

为什么你真的想这样做?如果您解释您的实际问题,我们可能会提供更好的选择。

于 2012-03-23T15:34:13.750 回答
3

您可以使用反射访问匿名内部类的方法。见getDeclaredMethods()。记得调用setAccessible(true)Method避免IllegalAccessException.

Object testObject = new Object() {
    private void testMe() { 
        System.out.println("testme");
    }
};
Method m = testObject.getClass().getDeclaredMethod("testMe");
m.setAccessible(true);
m.invoke(testObject); // prints out "testme"

另请注意,如果存在SecurityManagerthis 将不可能,请参阅对象反射的安全风险是什么?

警告:考虑到匿名内部类是一种一次性类定义。一旦使用,您将不再需要它们。就像@PéterTörök 所说,如果没有更多关于您的问题的上下文,很难判断,但是,如果您可以控制该类,最好将该类去匿名化(创建一个私有内部类,甚至是公共的),并将该方法公开给需要它的类。

于 2012-03-23T15:35:18.460 回答
1

匿名内部类默认是私有的。要与反射一起使用,您可以在这里查看 - Java 反射:如何检索匿名内部类?

于 2012-03-23T15:35:18.723 回答
1

匿名内部类具有包私有(默认)访问权限。在 Java 6 中,如果在静态上下文中声明它们是最终的,但在其他上下文中不是最终的。(我相信,但尚未测试,这在 Java 7 中已经改变,因此它们始终是最终的;请参阅Java 语言规范的第 15.9.5 节。)

例如,这个类有四个匿名内部类:

public class InnerTest {
    public Runnable foo1 = new Runnable() {
        public void run() {foo1();}
        void foo1() {}
    };
    private Runnable foo2 = new Runnable() {
        public void run() {foo2();}
        void foo2() {}
    };
    public static Runnable foo3 = new Runnable() {
        public void run() {foo3();}
        void foo3() {}
    };
    private static Runnable foo4 = new Runnable() {
        public void run() {foo4();}
        void foo4() {}
    };
}

当使用 javac(版本 1.6.0_26)编译时,它会生成四个匿名内部类。反编译javap -c揭示:

  • InnerTest$1( foo1) — 包私有
  • InnerTest$2( foo2) — 包私有
  • InnerTest$3( foo3) — 包私有和最终
  • InnerTest$4( foo4) — 包私有和最终

Note that the access of the variable to which the anonymous inner class instance is being assigned is irrelevant.

于 2012-03-23T16:24:37.090 回答