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)
Related
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.
I was trying to compile a few files in a package in java. The package name is library. Please have a look at the following details.
This is my Directory Structure:
javalearning
---library
------ParentClass.java
------ChildClass.java
I tried to compile in the following way:
current directory: javalearning
javac library/ParentClass.java //this compilation works fine
javac library/ChildClass.java //error over here
The following is the ParentClass.java:
package library;
class Parentclass{
...
}
The following is the ChildClass.java:
package library;
class ChildClass extends ParentClass{
...
}
The error is as follows:
cannot access ParentClass
bad class file: .\library\ParentClass.class
Please remove or make sure it appears in the correct sub directory of the classpath
You've got a casing issue:
class Parentclass
That's not the same as the filename ParentClass.class, nor is it the same as the class you're trying to use in ChildClass: class ChildClass extends ParentClass.
Java classnames are case-sensitive, but Windows filenames aren't. If the class had been public, the compiler would have validated that the names matched - but for non-public classes, there's no requirement for that.
The fact that you've ended up with ParentClass.class suggests that at some point it was declared as ParentClass, but then you changed the declared name and when recompiling, Windows just overwrote the content of the current file rather than effectively creating Parentclass.class.
Make sure your declared class name exactly matches the filename. You may well want to delete all your class files before recompiling, just to get out of a confusing state.
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.
I'm trying to get a class whose instance has already been created and I want to use that instance. The name of the needed class and the correct package is specified. However. I'm getting an java.lang.IllegalStateException stating that the specified class could not be found. All of the package names and the imports in each class have been checked and they all match.
Does anyone knows why this is being generated please?
its possible the wanted class isnt on your runtime class path. for more info read this: http://docs.oracle.com/javase/tutorial/essential/environment/paths.html
It gives an error "Could not find the main class: filename.java" How do I set the filename to be independent of the class names?
You can't ... In Java the file name has to match the name of the public class in the file
See Why are filenames in Java the same as the class name? for an explanation
Short Answer: You can't. One class per file is the java way. Accept that or find another language.
Longer Answer: You can but you probably don't want to.
If you have one public class and x number of non-public classes, you can put the all in the same file by nesting the non-public classes inside the public class. For example (in BlowFish.java):
public class BlowFish
{
class Hooty
{
}
class Sushi
{
}
}
you can't. a java class must be in a .java file with the same name.
maybe is into the manifesto file where you are defining this class as your main class
Sure you can. Just put version numbers in your classnames, as well.
Or keep the newest as the classname.java, with older versions getting version numbers.
Or drop the version numbers and use source code control.