Kabir
Kabir

Reputation: 1479

java.lang.ClassNotFoundException: A

I was testing an example of accessing private method from another class and got an exception

public class WithoutMain 
{       
    public static void main(String args[]) throws Exception
    {
        Class c = Class.forName("A");
        Object o = c.newInstance();
        Method m = c.getDeclaredMethod("message", null);
        m.setAccessible(true);
        m.invoke(o, null);
    }
}

public class A {

    private void message(){ 
        System.out.println("This is a private method.");
    }
}

Getting following exception

Exception in thread "main" java.lang.ClassNotFoundException: 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)

These 2 class resides in same package. Can anyone tell me why this exception shows?

Upvotes: 1

Views: 1410

Answers (6)

foolish1337
foolish1337

Reputation: 1

As already stated in answers before, needs full name.

To avoid manually typing it you can simply use:

Class<?> clazz = Class.forName(A.class.getName());

Upvotes: 0

tom
tom

Reputation: 354

The Java Class class isn't in your package, so it needs to know where the class is located otherwise it doesn't know where it is in order to load it(just like the classloader loads it from a full file path).

so

Class<? extends Object> c = Class.forName("A");

needs to be

Class<? extends Object> c = Class.forName("package.A");

where package is the full qualified name of the package so if the package is

foo.bar

it would become

Class<? extends Object> c = Class.forName("foo.bar.A");

Upvotes: 0

dharam
dharam

Reputation: 8096

You need to use the fully qualified name of a class to load it using Class.forName()

Now you may argue why? As in your case both the classes are in the same directory/package.

I would argue the other way, there is no rule defined in java that the class loader will look in the same directory first.

If you want to learn how class loading works, I would suggest you source code for the class java.lang.ClassLoader class

So when you invoke the Class.forName it uses delegation and the class loader which is assigned the job to load this class will not know the current package or any location. Hence, it needs the fully qualified class name.

One more tip, in java a fully qualified class name of a loaded class is <ClassLoader><packageName><className>. This is how the classes in JVM are uniquely identified.

Hope this helps

EDIT

Your code will work only in one condition and that is, if both the classes are in default package.

Upvotes: 4

Dave Newton
Dave Newton

Reputation: 160171

You need the FQN as per the docs:

Parameters:
   className - the fully qualified name of the desired class.

Upvotes: 1

Konstantin Yovkov
Konstantin Yovkov

Reputation: 62854

You have to provide the fully qualified name of the class, not only the simple class name.

Class c = Class.forName("<package>.A");

Upvotes: 2

Arhowk
Arhowk

Reputation: 921

Try changing

    Class c = Class.forName("A");

to

    Class c = Class.forName("yourPackagePath.A");

the forName method does not take in account the package of the user call.

Upvotes: 1

Related Questions