2014-01-27 89 views
8

为什么下面的代码会导致ClassNotFoundException为什么无法加载内部类? ClassNotFoundException

public class App02 { 

    public static class A { 
    } 

    public static void main(String[] args) throws ClassNotFoundException { 

     try { 
      System.out.println("A.class.getCanonicalName() = " + A.class.getCanonicalName()); 
      Class c = Class.forName("tests.App02.A"); //error on this line 
      System.out.println(c.getName()); 
     } 

     catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

输出:

A.class.getCanonicalName() = tests.App02.A 
java.lang.ClassNotFoundException: tests.App02.A 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Class.java:190) 
    at tests.App02.main(App02.java:15) 
+0

如果你有一个包'tests.App02'在它的一类'A'我应该'Class.forName'回报? –

+1

如果我有带'$'符号的名字,应该返回什么? :) –

+0

它实际上可以在Java中调用一个类'$'!!为什么,哦,人性! –

回答

13

尝试Class c = Class.forName("tests.App02$A")。它不是顶级课程,所以使用$来定位它。

+1

或者更确切地说,App02不是一个包,所以你不能使用'.'来下一个级别。 –

4

您需要使用$访问嵌套类

Class c = Class.forName("tests.App02$A"); 

当你编译你的类,你会发现,嵌套类被命名为:App02$A.class,包下tests。那会更有意义。

+0

@MarkoTopolnik不知道:) –

+0

这个术语是非常混乱的。最重要的是,每个人都假设* inner *意味着“需要封闭实例的嵌套类”,但即便如此,内部类也可以在静态上下文中声明。 'class Toplevel {static Object x = new Object(){}; }' –

+0

恩。匿名内部类。这就是它开始混淆更多的地方。首先看一个可能期望该实例具有与其关联的封闭实例。基本上,这取决于引用是否是“静态”。但是每当我感到困惑时,我就停下来看看字节码。这就是答案:) –

3

由于您使用的是规范名称,但你应该使用A.class.getName())。

在你的情况,你应该使用Class c = Class.forName("tests.App02$A");