2014-01-27 37 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");