In my main I have the following statement
Class booki = Class.forName("Book");
which throws a java.lang.ClassNotFoundException exception
when I use the full path like Class booki = Class.forName("javatests.Book"); it is ok.
The main class and the Book class are in the same package, I also tried using import static javatests.Book.*; but still it throws the exception if I don't set the full path javatests.Book. Can someone explain to me why?
Class.forName resolves a fully qualified class name to the class. Since a method does not know where it is called from neither the package of the calling class nor imports in the calling class play any role.
From docs Class#forName
public static Class<?> forName(String className)
throws ClassNotFoundException
Parameters:
className - the fully qualified name of the desired class.
So this will not throw ClassNotFoundException
Class booki = Class.forName("javatests.Book");
For example, it is not needed to import java.lang.* package in java program but to load class Thread from java.lang package you need to write
Class t = Class.forName("java.lang.Thread");
the above code fragment returns the runtime Class descriptor for the class named java.lang.Thread
You always need a qualified class name unless it's inside the same package. If i define a class foo in my package i can call a method Class testClass = Class.forName("foo") , but i can't call Class testClass = Class.forName("SecureRandom"); even if I import SecureRandom. That's just how the function works. It probably has a shortcut where it tries to find things inside local packages, but doesn't do much behind that.
Firstly the Book class must be in the package javatests.
the JVM load the class by name,through the classpath.
There is no class named "Book" in the classpath.
So JVM give you a ClassNotFoundException when excuse Class.forName("Book").
But 'Class.forName("javatests.Book")' tells JVM the class named 'Book' is in package 'javatests'.
So the JVM can find it and load it.
I hope my answer is helpful :)
JLS provides the following description:
Class lookup is always on behalf of a referencing class and is done through an instance of ClassLoader. Given the fully qualified name of a class, this method attempts to locate, load, and link the class.
The JDK uses one instance of ClassLoader that searches the set of directory tree roots specified by the CLASSPATH environment variable; and obviously it is not aware of the place (package) it has been called. That is why it needs fully qualified name.
Related
I have the following code:
Class<?> classType = Class.forName(typeClassName);
It keeps throwing an error everytime I try to run the code:
java.lang.ClassNotFoundException: EmailAddress
But I'm speciaifially importing the EmailAddress class into the class that I'm running the first code:
import ie.folder.EmailAddress;
How can this be?
If you are already importing the class there is no need to use reflection, you can just do
Class<EmailAddress> clazz = EmailAddress.class;
You would only really need to use Class.forName if you do not know the class name at the time you compile your program. If you still want to do that, you need to use the fully qualified class name (the imports do not matter, they are not considered at runtime, only during compilation).
Class<?> clazz = Class.forName("ie.folder.EmailAddress");
And you have to deal with the exception if that class could not be found or loaded.
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?
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.
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
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.
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.
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.
How can I mention the path of a class as in following code?
Class cl=Class.forName("SomeClass");
This works well if the "SomeClass" is located in the same directory of the calling class. But how to check for a class from a different directory, I saw the syntax for that is like xxxx.yyyy.class, but could not make out what those 'x's and'y's stand for. please help.
Thanks in advance.
Use the fully-qualified class name. For instance, to do this with the Java SE String class, which is in the java.lang package:
Class clazz = Class.forName("java.lang.String");
Those xxx and yyy stands for package names. Packages are normally represented by directories on disk with the same name as the package. When you create a class file you can specify which package the class goes by stating package xxx.yyy at the top of the file.
Referring to "SomeClass" without a package name will try to load a class named SomeClass in the default package.
Use Class.forName although make sure you deal with a possible ClassNotFoundException exception. This is a runtime exception so it does not mean you need to catch it. This is how you will know if you path to the class is correct. The problem is that if it cannot find the class funny things can happen with your code.
Class.forName(com.my.package.ClassName)
I have an issue where NoClasDefFoundError is being thrown. It puzzles me since I am using interfaces, and no class definition should be available. I have read through some posts which point to Classpath, but I don't believe that to be the issue here (although I may be wrong). I am using NetBeans 6.9.1 IDE.
I have created a sample setup to reproduce the issue. Four projects: Interfaces, Objects, Locator and Consumer. Below you will find the implementations.
At runtime consumer coplains about missing SomeObject implementation, which it should not be aware of since it is accepting interface.
Exception in thread "main"
java.lang.NoClassDefFoundError:
objects/SomeObject
What am I missing?
package interfaces;
public interface ISomeInterface { }
package objects;
import interfaces.ISomeInterface;
public class SomeObject implements ISomeInterface{ }
package locator;
import interfaces.ISomeInterface;
import objects.SomeObject;
public class Locator { public static ISomeInterface LocateImplementation() { return new SomeObject(); }}
package consumer;
import interfaces.ISomeInterface;
import locator.Locator;
public class Main { public static void main(String[] args) { ISomeInterface object = Locator.LocateImplementation(); }}
You can get a NoClassDefFoundError exception with interfaces just as you can with classes. Consider the "Class" in the name of the exception to be the .class file that is generated from compiling a class or interface, not a Java class.
This is saying that the class/interface objects.SomeObject isn't visible on your classpath. Check the location of that .class file and ensure that it's on your classpath - if you're positive it's there, give us some screen shots or something that might help to debug the problem.
Think of NoClassDefFoundError as a runtime linkage problem. JRE loaded one class (or an interface) and it references another class (or an interface), but that referenced class isn't found.
The only way this can happen if you have packaging/classpath issues such that your runtime environment doesn't reflect how things are at build time.
If you are launching this from IDE, make sure that you aren't ignoring any errors and launching anyway. Some classes will not be generated that way.
Usually I run into these problems not when a class is missing, but when there is an error in the static initializers.
Try running your code in a debugger, and set the exception breakpoint to break when any exception is thrown, whether caught or not. I bet you have an uncaught exception in the static initializer for some reason.
In the locateImplementation() method you are returning "new SomeObject()",
JVM needs to have its definition when called. I think it is missing.
You should check if your SomeObject class is in class path because -
Well the JVM will be running the below code -
ISomeInterface object = Locator.LocateImplementation();
and when it does that it will call Locator.LocateImplementation(). This code internally tries to instantiate your SomeObject class which it does not find in the classpath.
So your below understanding
It puzzles me since I am using
interfaces, and no class definition
should be available.
Is not really valid.
Any Interface must be declared inside class
public class Calbacks {
public interface IBaseFragmentInterface {
void NotifyMainActivity();
}
}
I have found one error in my Java program:
The public type abc class must be defined in its own class
How can I resolve this error? I am using Eclipse. I am new to Java programming.
Each source file must contain only one public class. A class named ClassName should be in a file named ClassName.java, and only that class should be defined there.
Exceptions to this are anonymous and inner classes, but understanding you are a beginner to Java, that is an advanced topic. For now, keep one class per file.
Answering your addition: it is OK to inherit classes and that's totally fine. This does not matter, each class should still have its own file.
Public top-level classes (i.e. public classes which aren't nested within other classes) have to be defined in a file which matches the classname. So the code for class "Foo" must live in "Foo.java".
From the language specification, section 7.6:
When packages are stored in a file system (ยง7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This rule, which doesn't have to be followed by compilers, is pretty much universally adhered to.
Ok, maybe an example will help.
In file MySuperClass.java:
public class MySuperClass {
// whatever goes here
}
public class MySubClass1 extends MySuperClass {
// compile error: public class MySubClass1 should be in MySubClass1.java
}
class MySubClass2 extends MySuperClass {
// no problem (non-public class does not have to be in a file of the same name)
}
In file MySubClass3.java:
public class MySubClass3 extends MySuperClass {
// no problem (public class in file of the same name)
}
Does that make things clearer?
A public class with the name of "abc" must be in a file called abc.java
You can create a new class an a existing file if it's private, but you should not do this.
Create one file per class.
Eclipse does that for you, if you create a new class.
For programming Java, you have to understand the construct of classes, packages and files. Even if Eclipse helps you, you have to know it for yourself. So start reading Java books or tutorials!