2012-03-23 100 views
0

默认情况下,匿名内部类是否是私有的?我可以让它们公开吗?Java中的公共匿名内部类

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

+1

如果它是一个匿名的内部类,编译器将如何知道去哪里调用这些方法?为什么你不只是创建一个公共类,并在你需要的地方使用它而不是使用匿名类? – jzworkman 2012-03-23 15:33:55

回答

2

您可以通过反射访问匿名内部类的方法。请参阅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所说,没有更多关于你的问题的背景很难说清楚,但是,如果你能控制这个类,那么可能会更好地对这个类进行匿名化(使私人内部类,甚至公开),并将该方法公开给需要它的类。

7

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

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

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

+0

我不同意。非匿名内部类和匿名内部类之间的唯一区别是后者没有名称。其原因是简洁,而不是安全。所以匿名类的原因不能被公开只是没有提出的语法。恕我直言。 – Dims 2012-03-23 16:07:17

+0

+1虽然(这是匿名内部类固有的),但如果您拥有实例,则不需要使用编译器生成的类名称。 – 2012-03-23 16:10:11

+0

@XaviLópez的确如此。如果你确实有实例,为什么你需要反思? – 2012-03-23 16:14:57

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$1foo1)—包私人
  • InnerTest$2foo2)—包私人
  • InnerTest$3foo3)—包私人和最终
  • InnerTest$4foo4)—包专用并且最终

注意,其中匿名内部类的实例是被分配的变量访问是无关紧要的。