Java中的公共匿名内部类

时间:2012-03-23 15:28:16

标签: java public anonymous-inner-class

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

我需要通过反思来访问方法。

4 个答案:

答案 0 :(得分:7)

匿名内部类是匿名的,原因是:它们不能直接从外部世界访问,只能通过引用变量/方法参数访问。 (出于同样的原因,他们也是私人的。)

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

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

答案 1 :(得分:3)

您可以使用反射访问匿名内部类的方法。见getDeclaredMethods()。 请务必致电Method上的setAccessible(true),以避免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"

另请注意,如果有SecurityManager这是不可能的,请参阅What is the security risk of object reflection?

警告:请注意,匿名内部类是一次性类定义。一旦使用,你再也不会在别处需要它们了。就像@PéterTörök所说的那样,没有更多关于你问题的背景就很难说,但是,如果你已经控制了那个类,那么对那个类进行去匿名化(制作一个私有的内部类,甚至是公共类)可能会更好,并将该方法公开给需要它的类。

答案 2 :(得分:1)

默认情况下,匿名内部类是私有的。要使用反射,您可以在这里查看 - Java reflection: How can I retrieve anonymous inner classes?

答案 3 :(得分:1)

匿名内部类具有包私有(默认)访问权限。在Java 6中,如果在静态上下文中声明它们,则它们是最终的,但在其他上下文中不是最终的。 (我相信,但尚未经过测试,这在Java 7中发生了变化,因此它们始终是最终的;请参阅Section 15.9.5 of the Java Language Specification。)

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

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) - package private
  • InnerTest$2 foo2) - package private
  • InnerTest$3 foo3) - 包私有和最终
  • InnerTest$4 foo4) - 包私有和最终

请注意,分配匿名内部类实例的变量的访问权限是无关紧要的。