tags:

views:

248

answers:

5
class HelloObject {
    void speak() {
     System.out.println("Hello (from object)!");
    }
}
class HelloTester {
    public static void main(String[] args) {
     HelloObject object = new HelloObject();
     object.speak();
    }
}

When I change the "HelloTester" class name to something like "HelloTester2", the program suddenly works. The class file is called ClassesBegin.java.

Why does the java program not work when I try to change the name of the class?

EDIT: Sorry I should have clarified more. I changed the class name to HelloTestera and this is the error I get: Exception in thread "main" java.lang.NoClassDefFoundError: HelloTester But it works even when the file name has nothing to do with a class name. It works with HelloTester when the file name is ClassesBegin.java

+7  A: 

You need to change the file name, not just the class name.

In Java, the .java and .class names have to be identical to the class name.

Hence, each class has to go to a separate file with its name so that a separate .class file is created.

Putting two different classes in the same file is a C++ practice that works with its compilation model, not with Java.

Edit: User ended up clarifying what caused his error, so obviously my answer here is not relevant. All the above applies to public classes. You can pull that off for package-level classes though I have to say that I consider that a horrible practice. If you're going to have something used by multiple classes in your package, give it its own file. If it's used just by one class, make it an inner class...

Uri
This is only true for public classes.
Fabian Steeg
How would you make a top level class private? My understanding is that only inner classes can be private.
Uri
As for default-level classes, well, that's true, but I doubt that he left out the public on purpose.
Uri
But it does work that way, be it on purpose or not.
Fabian Steeg
Even for the class that contains main? I admit that I've never tried compiling a file with main() contained in a different classname. Don't you need to have that classfile with the correct name?
Uri
I tried the example and running the class with the main method works fine (in Eclipse).
Fabian Steeg
It's not a C++ practice. It's possible in C++, but not common.
strager
@strager: I agree. I did see many of my students doing it over the years, though, perhaps in a weird attempt to reduce the number of files they submit in assignments.
Uri
@Fabian: Hmm, strange, it does work. I'm wondering why it let me pull that off. I've never used a non-public main
Uri
+1  A: 

You are allowed to have as many non-public classes in your ClassesBegin file as you like in terms of compilation. But only the public (ClassesBegin in this case; until you change the name of the file) is able to be used externally.

In particular, the main() method must be public, and in a public class to be able to be found by java. Rename your file to HelloTester to make it work.

Or - rename the HelloTester class in your IDE, which probably is relaming the file automatically, since it has a main method, and the IDE knows that it needs to be the public class...

Stephen
+1  A: 

The easiest way to do this is:

1) only one top level class per file 2) the name of the class and the name of the file must match (name and CasE)

This makes it easier to find you classes (the name of the class is the name of the file) and you don't wind up with some odd issues where the compielr cannot find all of the classes to copmpile.

Java also has a restriction where the name of a public class 100% must be the same as the name of the file. The restriction is only on public classes (or interfaces or enums). You can have as many non-public types as you want in a file... but don't do that - stick with one top level class/interface/enum per file.

TofuBeer
A: 

You write:

I changed the class name to HelloTestera and this is the error I get: Exception in thread "main" java.lang.NoClassDefFoundError: HelloTester

It seems you are not actually running the renamed class but the old one. Did you call Java with the new changed class name? Did you recompile the file before running the class?

After renaming the class, you should first run:

javac ClassesBegin.java

And then:

java HelloTestera

Which for me yields:

Hello (from object)!

Usually, when using an IDE, these issues are handled for you (compile before running).

Fabian Steeg
+1  A: 

"EDIT: Sorry I should have clarified more. I changed the class name to HelloTestera and this is the error I get: Exception in thread "main" java.lang.NoClassDefFoundError: HelloTester But it works even when the file name has nothing to do with a class name. It works with HelloTester when the file name is ClassesBegin.java"

The file name and the class name must match if the class is public.

If you chagned the class name to "HelloTestera" but ran "java HelloTester" (which is what java.lang.NoClassDefFoundError: HelloTester would indicate) then the issue is that you passed the wrong class name to "java".

But save yourself a lot of time and name the class and the file the same thing and keep it at one top level class per file. A simple way to "force" that is to make all of your classes public for now (you can only have one public class per file). This will really save you from making some mistakes.

TofuBeer