16

Why does the following code cause 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();
        }
    }
}

Output:

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)
The Guy with The Hat
  • 10,836
  • 8
  • 57
  • 75
Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385

4 Answers4

21

Try Class c = Class.forName("tests.App02$A"). It's not a top-level class, so use $ to locate it.

Paul Hicks
  • 13,289
  • 5
  • 51
  • 78
7

You need to use $ to access the nested class:

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

When you compile your class, you will notice that the nested class is named as: App02$A.class, under package tests. It would make more sense then.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • @MarkoTopolnik Didn't knew that :) – Rohit Jain Jan 27 '14 at 20:03
  • The terminology is notoriously confusing. The high point is that everybody assumes *inner* means "nested class requiring an enclosing instance", but even that isn't true: an inner class may be declared in a static context. `class Toplevel { static Object x = new Object() {}; }` – Marko Topolnik Jan 27 '14 at 20:05
  • Umm. Anonymous inner class. That's where it starts to confuse more. On first look one might expect that instance to have the enclosing instance associated with it. Basically, that depends whether the reference is `static` or not. But whenever I feel confused, I stop there and look out for bytecode. That answers it :) – Rohit Jain Jan 27 '14 at 20:10
  • All anon classes are inner, and *inner* is about the restriction that it can't contain static members. Yes, if the anon class finds itself in a static context, then clearly there can't be any enclosing instance available. – Marko Topolnik Jan 27 '14 at 20:13
4

Because you are using a canonical name, but you should use name (A.class.getName()).

In your case you should use Class c = Class.forName("tests.App02$A");

Filipp Voronov
  • 4,077
  • 5
  • 25
  • 32
2

There is a helpful util in commons-lang which support these classes:

org.apache.commons.lang3.ClassUtils.get("tests.App02.A")
Inshua
  • 1,355
  • 1
  • 12
  • 12