173

I have a file Test.java and the following code inside it.

public class Abcd { //some code here } 

Now the class does not compile, but when I remove the public modifier , it compiles fine.

What is the reasoning behind Java allowing us to compile a class name that is different from the file name when it is not public.

I know it is a newbie question, but I'm not able to find a good explanation.

7
  • 28
    Because Java. (Because it's not public, and doesn't have to follow the same naming convention. Beyond that, you'd need to ask the folks that invented it.) Commented Nov 25, 2013 at 14:40
  • 2
    I doubt there is a "good explanation". It was a requirement for public classes, but it was deemed unnecessary for non-public classes. Commented Nov 25, 2013 at 14:40
  • 2
    Seems like a similar question: stackoverflow.com/questions/7633631/… Commented Nov 25, 2013 at 14:41
  • 4
    Why so many upvotes for this question, first of all its duplicate question: stackoverflow.com/questions/7633631/… Commented Nov 26, 2013 at 12:46
  • 2
    @ Ramesh : title and content of this question is better..(than the other similar ones) Commented Nov 27, 2013 at 5:17

8 Answers 8

327

The rationale is to allow more than one top-level class per .java file.

Many classes—such as event listeners—are of local use only and the earliest versions of Java did not support nested classes. Without this relaxation of the "filename = class name" rule, each and every such class would have required its own file, with the unavoidable result of endless proliferation of small .java files and the scattering of tightly coupled code.

As soon as Java introduced nested classes, the importance of this rule waned significantly. Today you can go through many hundreds of Java files, never chancing upon one which takes advantage of it.

Sign up to request clarification or add additional context in comments.

19 Comments

+1, this actually provides a reason, which is the question.
+1 for the historical info especially - I suspect that with the advent of nested / anonymous classes, if the same decision were to be made now (not caring about backwards compatibility) it would make much more sense to just allow one top level class per file.
@berry120 Quite probably, because this allowance complicates the file search when compiling.
@Val Denying that other people would rather use a text editor and CLI tools to develop because you the IDE you prefer exists is just as silly as saying there's no point in creating IDEs because you can do development without them. Both approaches are used by good developers to create quality code; and the only thing smaller than the odds of all developers settling one one of them and singing kumbaya is the odds that we'll all agree on what the single best programming language is.
The combination of Emacs (or Vim, pick your poison) and the Unix shell utilities are perhaps not as everything-at-your-fingertips as a modern IDE, and they're certainly harder to learn, but they have two overwhelming advantages compared to every IDE I've ever tried: they never crash, no matter how huge the codebase is, and they can keep up with my typing.
|
81

The reason is the same as for the door plates. If some person officially resides in the office (declared public) his/her name must be on the door tag. Like "Alex Jones" or "Detective Colombo". If somebody just visits the room, talks to an official or cleans the floor, their name does not have to be officially put on the door. Instead, the door can read "Utilities" or "Meeting room".

Official name or MyClass.java Meeting room or Test.java

5 Comments

Definitely an interesting analogy; it might be even better with a little bit of explanation of how it relates directly. The OP might have some difficulty making the connection (though I understand it perfectly)
@AndrewBarber I don't think the analogy really fits since it doesn't model the one public class, sharing the file with several package-private classes. It's like the door plate reading "Heather Santee, Manager", but the room actually containing Heather and her two secretaries.
@MarkoTopolnik I shouldn't have gotten involved in this; I am class-A horrible at analogies! ;)
@AndrewBarber I wanted to write it, anyway; you just gave a push :) The analogy also fails to express the most acute concern: just due to this feature the compiler must parse all the files to discover all the classes where otherwise it could just read the directory listing and know the names of all top-level classes.
@AndrewBarber, the analogy perfectly fits the idea of directory, in the long corridor you can quickly find a person by just glancing on the door plates, you do not need to enter each room and ask.
30

The Java specification states you can only have at most one public class per file. In this case, the class name should match the file name. All non-public classes are allowed to have any name, regardless of the file name.

13 Comments

But "what is the reasoning behind Java allowing" us this?
@MarkoTopolnik Because it doesn't prevent us :D
@MarounMaroun But what is the reasoning behind not preventing us?
@Marko Java allows to have multiple classes defined in the same file (as long as only one of them is public). As all classes within the same package must have a different name, there is no other option than allowing non-public classes to have a name other than the file name.
My 2 cents: maybe it was designed this way for quicker localization of classes inside classpath. With this convention, inspecting the file names/paths is sufficient for class discovery. Without this convention, the classpath class loader might need to open and parse files in order to find classes
|
14

I think allowing them is a prerequisite for nested classes. Anonymous Classes in particular dramatically reduce the number of .java files required. Without support for this, you would need lots of single method interface implementations in their own separate files from the main class they are used in. (I'm thinking of action listeners in particular)

There is a good explanation of all nested classes in the Nested Classes Java tutorial on Oracle's website, which has examples of each. It also has a reason they are useful, which I'll quote:

Why Use Nested Classes?

Compelling reasons for using nested classes include the following:

  • It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.

  • It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.

  • It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.

(emphasis mine)

I am not familiar with Java spec back in the early days, but a quick search shows inner classes were added in Java 1.1.

2 Comments

What should one do in cases where a type is only useful within another type, but instances of the former type are not associated with instances of the latter?
Nested classes are the Java 1.2 way of doing lambdas or 'First Class Functions when Everything is An Object'. This is changing in 1.8 Syntax. They're also used when we want to model Algebraic Data Types in Java's Type system.
12

I look at it the other way round. The natural state of affairs would be for the programmer to pick both the class name and the file name independently. Probably in order to simplify finding public classes from outside a package during compilation, there is a special restriction that a public class be in a file with the corresponding name.

Comments

4

Note that Java is case-sensitive, but the filesystem need not be. If the file's base name is "abcd", but the class is "Abcd", would that conform to the rule on a case-insensitive filesystem? Certainly not when ported to a case-sensitive one.

Or suppose you happened to have a class called ABCD, and a class Abcd (let's not get into that being a bad idea: it could happen) and the program is ported to a case insensitive filesystem. Now you not only have to rename files, but also classes, oops!

Or what if there is no file? Suppose you have a Java compiler which can take input on standard input. So then the class has to be named "StandardInput"?

If you rationally explore the implications of requiring file names to follow class names, you will find that it's a bad idea in more than one way.

1 Comment

I agree with what you have to say, but I don't know that it particularly answers the question except perhaps to the extent that some of the problems resulting from the naming architecture could be eased by allowing non-public class names to be different from file names. BTW, with regard to case-sensitivity, if I were deriving a language, in any scope were Foo was declared, the identifiers FOO, foo, fOo, etc. would all be "undefined" even if they existed within outer scopes. Such a design would eliminate the case-sensitivity issue for filenames.
3

Also one other point that many answers missed to point out is that without the public declaration, the JVM would never know which classes' main method needs to be invoked. All classes declared in one .java file can all have main methods, but the main method is run on only the class marked as public. HTH

1 Comment

This is not correct. You can have a file named two.java with the contents: class one { public static void main(String[] args){ System.out.println("Hello!"); System.out.println("World!"); } } Now, when you compile it "javac two.java", you get a class file "one.class" and then when you run "java one", it correctly outputs: Hello! World! It runs because we say "java one", JVM knows to look for a class file "one.class", find the main method in it, and run it. Your second line is also not correct.
0

Because of a java file can contains more than one class, it may have two classes in one java file. But a java file have to contain a class as the same name as file name if it contains a public class.

1 Comment

No, that rule is only applicable for public classes.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.