Why only one public class per Java file? [duplicate] - java

In any Java file, why can we have only one public class whose name is same as the Java file name?

It forces all Java code to be organized in a certain way, which in the long run helps improve code readability.
The Java designers chose a strict approach that enforces their idea of good design practices, and this is part of that theme. Contrast that with the anything-goes attitude in Perl.

According to this source, it is for efficient compilation :
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
The same applies also for imports of source files in IDEs. Another reason would be reasonable source sizes.

These are the rules. Although it is not quite true. You can define internal classes inside you "main" class like this:
public class A {
public class B {
...
}
}

Courtesy of Dr Heinz Kabutz and his excellent newsletter....
Why is each public class in a separate
file?
This is a question that I have
frequently been asked during my
courses. Up to now I have not had a
good answer to this question. In
section 1, we read: "Although each Oak
compilation unit can contain multiple
classes or interfaces, at most one
class or interface per compilation
unit can be public".
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.

We can have only one top level public either class or interface in any java compilation unit ( .java source file ).
But there can be any number of default classes/interfaces per src file.
why:
JLS leaves the option to the java compiler. And most of the compiler implementations force to have file name same as :
(1) the public class/interface name
(2) if there is a main method and no public class then any name
(3) If there is main method and public class then main method should be in that public class
(4) if there is no public class and no main method then any valid name which may or may not be matching with the class/interface names in the file.
From (2): If two public classes allowed, we should give the file two names which is terribly meaningless to file system.
From (3): If two public classes allowed, we should have two main methods which is terribly meaningless to java
Hence a Java source file can have one only public class.
I think the above 4 points are forced by compiler to make the job of both compiler and jvm to find particular java source file or class file easy-so-quick for the compilation/loading/linking. Java has such built in restrictions which developers should follow to have better programming.
Source: My readings and understanding.

To understand the basic reason behind these restrictions, let's suppose compiler doesn't give compile error for not naming file name same as public class name.
Suppose there is a package A
A
/ \
file1.java file2.java
file1.java
package A;
class file1
{
public static void main(String args[])
{
}
}
public class file3
{
public static void main(String args[])
{
}
}
Now as we know that a public class can also be accessed outside the package, now it will become the responsibility of a developer to make it accessible to the outside world. Let's see how:
Suppose package A is containing only Java files(no class files) and some class outside the package A tries to access public class file3, compiler will first try to find file3.class ( not available ), then it will try to find file3.java ( not available ). So even though file3 class is public in nature, it is not visible to the outside world. So if a compiler puts the restriction that if a file is containing public class, it should be named same as the public class name, then above issue can be resolved and the developer won't have to think of exposing public class to the outside world.
Compiler also puts the restriction that there should be atmost one public class per Java file, so that every public class can be accessed by the outside world.

Java utilizes this convention to find class/interface bytecode by starting at the classpath and scanning for the package hierarchy in subdirectories. Filesystem representation of this hierarchy also enforces some basic rules.
Any two Java classes or interfaces
in the same package cannot have the
same name. File names would
conflict.
Any two Java packages in
the same parent package could not
have the same name. Folder paths
would conflict.
A class has visibility to all classes in the same package without modification
to the classpath.

To have an understanding between the compiler and the programmer.It is a rule that the source code must have atmost one public class and that class must contain the main function.So without any confusion/restriction the compiler can access(public) the class and name the class name to the class file.Also since this class contains the main(), executing the class file will give correct flow

Public modifier with a class is exposed to the world that means any other class which is outside of the package can also access it to resolve dependency.
Now this dependency chain containing multiple classes are verified two times - one is while compilation ( one level of dependency is verified) & other one is while execution ( whole dependency chain is verified ).
Now suppose there is public class (class A) whose source file name is something different from class name. Now if some other class (say class B) depends on it , then while compilation of class B , java compiler will surely check where that class A is located & for that compiler has to go thru all the packages in search of class A ,which is time consuming.
Now suppose in the same scenario we give source file name of class A as A.java , then while compiling class B , compiler will search for class A & for that it only need to find source file whose name is A.java , so it doesn't need to go thru all packages ( which may contain multiple classes) it will now only search that package in which a source file A.java is present.
So from compilation time , performance point if view one source file should have one public class.

It enables a more efficient lookup of source (.java) and compiled (.class) files during compilation (import directive) and a more efficient classloading during execution. The idea being: if you know the name of a class, you know where it should be found for each classpath entry. No indexing required.

I think that this may be a possible reason.
There can be only one public class in a java file because the name of java file is same as the name of public class.And obviously we can't have a file with two different names.

It is how it has been designed and I am not sure if the reason is documented. But here is a good reason on why it is done that way. Let's assume we have two public classes Y & Z in a file named Y.java. Now, let's assume a different class X is using Z. Now, when we compile X, the compiler first tries to locate Z.class and if it cannot find it, then it tries to locate Z.java so that it can compile it automatically. But, since we only have Y.java, the class Z cannot be located and hence we get a compilation error. So, we do need to place them in separate files.

Class A{
}
public Class B{
}
So this is correct becoz A is not public and compiler will not confuse that which class compiler should execute.
public Class A{
}
public Class B{
}
So this is incorrect becoz here compiler get confused which class should execute becoz both are public.

Related

Questions about given answer on topic of "why only one public class per file "

I came accros following Question: Why only 1 public class in Java file
and there was this Answer:
To understand the basic reason behind these restrictions, let's
suppose compiler doesn't give compile error for not naming file name
same as public class name.
Suppose there is a package A
A
/ \
file1.java file2.java
file1.java
package A;
class file1
{
public static void main(String args[])
{
}
}
public class file3
{
public static void main(String args[])
{
}
}
Now as we know that a public class can also be accessed outside the
package, now it will become the responsibility of a developer to make
it accessible to the outside world. Let's see how:
Suppose package A is containing only Java files(no class files) and
some class outside the package A tries to access public class file3,
compiler will first try to find file3.class ( not available ), then it
will try to find file3.java ( not available ). So even though file3
class is public in nature, it is not visible to the outside world. So
if a compiler puts the restriction that if a file is containing public
class, it should be named same as the public class name, then above
issue can be resolved and the developer won't have to think of
exposing public class to the outside world.
Compiler also puts the restriction that there should be atmost one
public class per Java file, so that every public class can be accessed
by the outside world.
But wouldn't we use something like import folder.packagename.filenameofclassfile3; so it would still technically work ?
if .class-file would not exist at the time of compilation
we would basically tell the compiler where to find the class file3 by using the full qualified name.
That explanation is more or less bogus. The real reason that the source file name of a public class file must be the same as the classname is because the spec says so. Simple as that.
import statements don't do anything special; you can import a class file that isn't used at all, and this will result in literal NOTHING whatsoever in the class file; if that imported class isn't even around when you run the code, it won't matter. This isn't python or a scripting language; import doesn't load it. at all. All import com.foo.Bar; does is say: "Anytime Bar shows up in this file as a type name, imagine it read com.foo.Bar instead" (and as a consequence, you can remove the import statement, and replace all occurrences of Bar with com.foo.Bar and the file works just the same.
As a consequence, putting the file name in an import statement isn't legal java.
Note also that if you put a non public class inside a file, even that file does NOT have the same name as that class, that is fine, and still results in that class existing on its own, in its own file, if you compile it (compiling 1 java file may produce more than 1 class file!)
If we'd have to guess at why whomever wrote in the java spec that public classes must be in a file named the same... who knows, really. There is no real reason for it. What the bogus answer you found is trying to drive at, is that if you use javac's very limited ability to find source files that must also be compiled (using the -sourcepath option, I guess this might indeed be easier, but note that there's nothing stopping you from writing code that refers to another non-public, not-yet-compiled class in the same package and run just javac ThatFile.java resulting in the same 'now the source file that needs to be compiled is hard to find' problem. Hence, why the answer you found, is bogus.

Disable enforcement of "The public type xyz must be defined in its own file"

Noob java question.
For my project, I have a class model defined in XML file, which I then transform into a model. For example:
<model>
<class name="abc"><field>one</field><field>two</field></class>
<class name="xyz"><field>f1</field><field>f2/field></class>
</model>
and this gets transformed into:
public class abc {
String _one;
String _two;
public String get_one() {
return _one;
}
... and so on you get an idea
Obviously, it would be a nuisance to transform each class into its own .java file. It would be much more manageable to pile them up in a single .java file. However, java has this requitement that each class must be defined in its own file, and the file name must match class name. Otherwise, compiler will show error: The public type XYZ must be defined in its own file
It's likely possible to define it like this:
public class ModelContainer {
public class abc {
...
}
public class xyz {
...
}
}
Is there another way? Ideally, I'm looking for a compiler switch or something of that kind, which would disable the requirement to have each class in its own file. I am using Eclipse if that makes any difference
If you're ok with using inner classes then yes, this will work but you'll have to obtain an instance of the outer class each time you want to instantiate an inner class:
public class ModelContainer {
public class abc {
...
}
public class xyz {
...
}
}
Also you can declare the nested classes as static, so it won't be necessary to instantiate the outer class first:
public class ModelContainer {
public static class abc {
...
}
public static class xyz {
...
}
}
Take a look at this post for additional details.
Interestingly enough, it's not actually a language requirement to have each top-level class in its own .java file:
If and only if packages are stored in a file system (§7.2), 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).
That said, since the compiler may enforce such a requirement, all portable code should conform to the practice.
Regarding your specific case, you should consider the one-top-level-class-per-file rule to be a language requirement. The usual approach is in fact to generate a separate .java file for each class (there are a number of annoying aspects to using nested classes, even static ones), but you could work around this by using nested classes if you have a better reason than not closing and opening files.
An alternate, but slightly more-sophisticated approach would be to skip creating Java source at all. You could use a bytecode library such as Javassist or ASM to create class files directly. Essentially, you would be compiling your XML declaration to executable code.
If you are creating simple value objects as shown, this would be pretty easy.
You seem to have a problem with generating large numbers of files, so you could write the class files directly into a JAR file (using the ZIP I/O classes) and generate your synthetic classes as a single library file.
(You might wish to mark these classes as synthetic, although the XML declaration could be considered source code, meaning that they are not technically synthetic.)
The compiler switch you want doesn't exist. Ensuring that each class is in a correctly-named file - and in the correct place in the directory hierarchy, assuming you're organizing your classes in packages - is always enforced by the Java compiler. Most Java devs wouldn't dream of turning this off, as this way of organizing one's source code is considered good practice. (Therefore Java devs have minor nightmares when attempting to navigate large, unruly projects in languages like C# that don't enforce this restriction.)
The only classes that don't need to obey this constraint are anonymous or inner classes, but your application shouldn't consist mostly of these.

Why does Java allow us to compile a class with a name different than the file name?

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.
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.
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".
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.
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.
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.
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.
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
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.

Class resides in different directory than what the package specifies - how come?

The following statements seem to disturbingly function:
robert#neghvar:~/tmp> cat org/foo/Bar.java
public class Bar {
}
robert#neghvar:~/tmp> javac org/foo/Bar.java
robert#neghvar:~/tmp> javap org.foo.Bar
Compiled from "Bar.java"
public class org.something.Bar extends java.lang.Object{
public org.something.Bar();
}
Although the Bar class file is in the org/foo directory and declares the org.something package, the compiler does not complain. I was under the impression that java mandated a directory hierarchy which follows the package name. Was I mistaken? If so, what are the consequences of mixing up package names?
The source directory structure is not required to follow package naming (even though it almost always does by convention.)
I think the Sun/Oracle javac,javap,java,etc. tools (and all other Java implementations that I know of) are what mandate the subdirectory per package name component rule (along with the default class loaders). I couldn't find anything authoritative, but it doesn't seem to be a requirement of the Java language specification:
http://java.sun.com/docs/books/jls/third_edition/html/packages.html
It's purely convention. The compiler will use the package names.
Having said that, it's not usually a good idea to break with this convention. It'll cause inconsistency (the classes generated will be in directories following the package) and some confusion!

Why only 1 public class in Java file

In any Java file, why can we have only one public class whose name is same as the Java file name?
It forces all Java code to be organized in a certain way, which in the long run helps improve code readability.
The Java designers chose a strict approach that enforces their idea of good design practices, and this is part of that theme. Contrast that with the anything-goes attitude in Perl.
According to this source, it is for efficient compilation :
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
The same applies also for imports of source files in IDEs. Another reason would be reasonable source sizes.
These are the rules. Although it is not quite true. You can define internal classes inside you "main" class like this:
public class A {
public class B {
...
}
}
Courtesy of Dr Heinz Kabutz and his excellent newsletter....
Why is each public class in a separate
file?
This is a question that I have
frequently been asked during my
courses. Up to now I have not had a
good answer to this question. In
section 1, we read: "Although each Oak
compilation unit can contain multiple
classes or interfaces, at most one
class or interface per compilation
unit can be public".
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
We can have only one top level public either class or interface in any java compilation unit ( .java source file ).
But there can be any number of default classes/interfaces per src file.
why:
JLS leaves the option to the java compiler. And most of the compiler implementations force to have file name same as :
(1) the public class/interface name
(2) if there is a main method and no public class then any name
(3) If there is main method and public class then main method should be in that public class
(4) if there is no public class and no main method then any valid name which may or may not be matching with the class/interface names in the file.
From (2): If two public classes allowed, we should give the file two names which is terribly meaningless to file system.
From (3): If two public classes allowed, we should have two main methods which is terribly meaningless to java
Hence a Java source file can have one only public class.
I think the above 4 points are forced by compiler to make the job of both compiler and jvm to find particular java source file or class file easy-so-quick for the compilation/loading/linking. Java has such built in restrictions which developers should follow to have better programming.
Source: My readings and understanding.
To understand the basic reason behind these restrictions, let's suppose compiler doesn't give compile error for not naming file name same as public class name.
Suppose there is a package A
A
/ \
file1.java file2.java
file1.java
package A;
class file1
{
public static void main(String args[])
{
}
}
public class file3
{
public static void main(String args[])
{
}
}
Now as we know that a public class can also be accessed outside the package, now it will become the responsibility of a developer to make it accessible to the outside world. Let's see how:
Suppose package A is containing only Java files(no class files) and some class outside the package A tries to access public class file3, compiler will first try to find file3.class ( not available ), then it will try to find file3.java ( not available ). So even though file3 class is public in nature, it is not visible to the outside world. So if a compiler puts the restriction that if a file is containing public class, it should be named same as the public class name, then above issue can be resolved and the developer won't have to think of exposing public class to the outside world.
Compiler also puts the restriction that there should be atmost one public class per Java file, so that every public class can be accessed by the outside world.
Java utilizes this convention to find class/interface bytecode by starting at the classpath and scanning for the package hierarchy in subdirectories. Filesystem representation of this hierarchy also enforces some basic rules.
Any two Java classes or interfaces
in the same package cannot have the
same name. File names would
conflict.
Any two Java packages in
the same parent package could not
have the same name. Folder paths
would conflict.
A class has visibility to all classes in the same package without modification
to the classpath.
To have an understanding between the compiler and the programmer.It is a rule that the source code must have atmost one public class and that class must contain the main function.So without any confusion/restriction the compiler can access(public) the class and name the class name to the class file.Also since this class contains the main(), executing the class file will give correct flow
Public modifier with a class is exposed to the world that means any other class which is outside of the package can also access it to resolve dependency.
Now this dependency chain containing multiple classes are verified two times - one is while compilation ( one level of dependency is verified) & other one is while execution ( whole dependency chain is verified ).
Now suppose there is public class (class A) whose source file name is something different from class name. Now if some other class (say class B) depends on it , then while compilation of class B , java compiler will surely check where that class A is located & for that compiler has to go thru all the packages in search of class A ,which is time consuming.
Now suppose in the same scenario we give source file name of class A as A.java , then while compiling class B , compiler will search for class A & for that it only need to find source file whose name is A.java , so it doesn't need to go thru all packages ( which may contain multiple classes) it will now only search that package in which a source file A.java is present.
So from compilation time , performance point if view one source file should have one public class.
It enables a more efficient lookup of source (.java) and compiled (.class) files during compilation (import directive) and a more efficient classloading during execution. The idea being: if you know the name of a class, you know where it should be found for each classpath entry. No indexing required.
I think that this may be a possible reason.
There can be only one public class in a java file because the name of java file is same as the name of public class.And obviously we can't have a file with two different names.
It is how it has been designed and I am not sure if the reason is documented. But here is a good reason on why it is done that way. Let's assume we have two public classes Y & Z in a file named Y.java. Now, let's assume a different class X is using Z. Now, when we compile X, the compiler first tries to locate Z.class and if it cannot find it, then it tries to locate Z.java so that it can compile it automatically. But, since we only have Y.java, the class Z cannot be located and hence we get a compilation error. So, we do need to place them in separate files.
Class A{
}
public Class B{
}
So this is correct becoz A is not public and compiler will not confuse that which class compiler should execute.
public Class A{
}
public Class B{
}
So this is incorrect becoz here compiler get confused which class should execute becoz both are public.

Categories

Resources