2014-01-27 8 views
8

Warum verursacht der folgende Code ClassNotFoundException?Warum kann die innere Klasse nicht geladen werden? 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(); 
     } 
    } 
} 

Ausgang:

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

Was soll 'zurückkehren Class.forName', wenn Sie in ein Paket' tests.App02' mit einer Klasse 'A' haben? –

+1

Was sollte es zurückgeben, wenn ich Namen mit '$' Symbol hätte? :) –

+0

Es ist tatsächlich möglich, eine Klasse '$' in Java aufzurufen !? Warum, oh die Menschheit! –

Antwort

13

Versuchen Class c = Class.forName("tests.App02$A"). Es ist keine Top-Level-Klasse, also benutze $, um es zu finden.

+1

Oder genauer gesagt, App02 ist kein Paket, also können Sie '.' nicht verwenden, um in die nächste Ebene zu gelangen. –

4

Sie müssen $ verwenden, um die verschachtelte Klasse zuzugreifen:

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

Wenn Sie Ihre Klasse kompilieren, werden Sie feststellen, dass die verschachtelte Klasse benannt als: App02$A.class unter Paket tests. Es wäre dann sinnvoller.

+0

@MarkoTopolnik Wusste das nicht :) –

+0

Die Terminologie ist notorisch verwirrend. Der Höhepunkt ist, dass jeder annimmt, dass * inner * bedeutet "geschachtelte Klasse, die eine umschließende Instanz benötigt", aber selbst das ist nicht wahr: Eine innere Klasse kann in einem statischen Kontext deklariert werden. 'Klasse Toplevel {statisches Objekt x = neues Objekt() {}; } ' –

+0

Umm. Anonyme innere Klasse. Da fängt es an, mehr zu verwirren. Auf den ersten Blick könnte man erwarten, dass dieser Instanz die umschließende Instanz zugeordnet ist. Grundsätzlich hängt das davon ab, ob die Referenz "statisch" ist oder nicht. Aber wenn ich mich verwirrt fühle, höre ich auf und halte Ausschau nach Bytecode. Das beantwortet es :) –

3

Da Sie einen kanonischen Namen verwenden, aber Sie sollten Name (A.class.getName()) verwenden.

In Ihrem Fall sollten Sie Class c = Class.forName("tests.App02$A");

Verwandte Themen