Reputation: 45
I have developed a normal Java project and I am trying to understand the difference between ClassNotFoundException
and NoClassDefFoundException
. I have found one weird behavior, which is that I need to include the whole package structure when I am calling Class.forName()
.
See the code below:
package org.com;
public class MainApp {
public static void main(String[] args) {
try {
Class cls = Class.forName("org.com.MainApp");
System.out.println("Class = " + cls.getName());
} catch(ClassNotFoundException ex) {
System.out.println(ex.toString());
}
}
}
If I use Class.forName("MainApp")
instead of Class.forName("org.com.MainApp")
an exception is thrown.
Can someone please explain the actual reason for this?
Upvotes: 3
Views: 1697
Reputation: 38950
Simple answer:
Same class may be part of multiple packages and JVM is not sure which class you are want to load.
You may have MainApp
class in package1
and package2
.
To avoid ambiguity, fully qualified class name is required in Class.forName
e.g.
Class.forName("package1.MainApp")
Class.forName("package2.MainApp")
Notes from documentation page:
public static Class<?> forName(String className)
throws ClassNotFoundException
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to: Class.forName(className, true, currentLoader)
Parameters:
className - the fully qualified name of the desired class.
Returns: the Class object for the class with the specified name.
Upvotes: 1
Reputation: 533880
When you compile code, the compiler knows which package you are compiling and which classes you have imported, so when you give it a class name it can check these things to find which fully qualified class name you meant.
However, Class.forName
is method on the class Class
. All it knows is what you passed it, the class name. It doesn't know the package of the caller, nor what imports you used. Only the fully qualified class name can work.
Upvotes: 1
Reputation: 11988
Basically, because the contract says so:
className - the fully qualified name of the desired class.
You could very well have two classes named MainApp
, in different packages. How would the classloader know which class to load if you omit the fully qualified name (i.e. including the package)?
In other words, it is a design desicion, and in my opinion, a good one.
Class.forName("MainApp")
would actually try to load a class named MainApp
located in the default package, that is no package name is specified in the class.
Upvotes: 7
Reputation: 28742
Class.forName has no concept whatsover of your class or where it's called from.
It's a general purpose tool.
For example:
You are the ONLY person in the city called alexander. You order a package by amazon and say, deliver it to Alexander.
You, from your perspective are the only one alexander in the city, quite easy not?
Now look from the perspective of amazon.. they have no clue where to send it.
The same logic applies to class.forName.
Upvotes: 2
Reputation: 20155
Because your class exist in that Package and forName method requires Fully Qualified name
Suppose if java has a AI to identify your classes by specifying only name, what will happend when you specify "Date" ?
Class cls = Class.forName("Date");
Is it need to give you java.util. Date
class or java.sql.Date
class or any third party library Date class ?
Thats why you need to specify package name to uniquely identify that class
Upvotes: 5