Reputation: 1479
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
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
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
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
Reputation: 160171
You need the FQN as per the docs:
Parameters:
className - the fully qualified name of the desired class.
Upvotes: 1
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
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