Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Why a Single Java Source File Can Not Have More Than One Public Class

DZone's Guide to

Why a Single Java Source File Can Not Have More Than One Public Class

This article looks behind-the-scenes at why Java won't allow more than one public class in a single Java source file.

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

According to Java standards and common practices, we should declare every class in its own source file. And even if we declare multiple classes in a single source file (.java), still each class will have its own class file after compilation. But the fact is that we can declare more than one class in a single source file with these constraints,

  • Each source file should contain only one public class and the name of that public class should be similar to the name of the source file.
  • If you are declaring a main method in your source file then main should lie in that public class.
If there is no public class in the source file then main method can lie in any class and we can give any name to the source file.

If you are not following the first constraint then you will receive a compilation error saying “The public type A must be defined in its own file”. While if you are not following the second constraint you will receive an error “Error: Could not find or load main class User” after execution of the program, and if you try this in Eclipse, then you will not get the option to execute the program.

Here we are talking about only top level classes, we can declare more than one public inner class.

Why Only One Public Class Per Source File

Now we know that we can’t declare more than one public file in a single source file. Now we will look at why we can’t do this or why it is not allowed in Java. 

Well, actually it is an optional restriction according to Java Language Specification (Section 7.6, Page No. 209), but it is followed by the Oracle Java compiler as a mandatory restriction. According to Java Language Specification:

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 restriction implies that there must be at most one such type per compilation unit. 
This restriction makes it easy for a Java compiler to find a named class within a package. 
In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units. 

For example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket , and the corresponding object code would be found in the file Toad.class in the same directory.

The above clarification is little bit difficult to understand, So let’s replace the “type” word with actual a class Toad to get more clarification:

Java compiler may give an error if Toad class is not found in Toad.java and either of following is true 
  • Toad class is referred in other classes in same package.
  • Toad class is declared public.
This restriction implies that there must be at most one such Toad class per compilation unit. 
And the reason behind this is, 
This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package.

To get a more clear picture, let's imagine there are two public classes—public class A and public class B—in the same source file, and class A has reference to the not-yet-compiled class B. And we are compiling (compiling-linking-loading) class A now while linking to class B—the compiler will be forced to examine each *.java files within the current package because class B doesn’t have it’s specific B.java file. So, in the above case, it is a little bit time consuming for the compiler to find which class lies under which source file and in which class the main method lies. 

So the reason behind keeping one public class per source file is to actually make the compilation process faster because it enables a more efficient lookup of source and compiled files during linking (import statements). The idea is if you know the name of a class, you know where it should be found for each classpath entry and no indexing will be required. 

And also as soon as we execute our application, JVM by default looks for the public class (since there are no restrictions and it can be accessible from anywhere), and it also looks for public static void main(String args[]) in that public class. The public class acts as the initial class from where the JVM instance for the Java application (program) is begun. So when we provide more than one public class in a program the compiler itself stops you by throwing an error. This is because later we can’t confuse the JVM as to which class is to be its initial class, because only one public class with the public static void main(String args[]) is the initial class for JVM. 

But why can we declare more than one non-public class (default access) in a single source file?

Although there is no particular specification or reference to point out why it is allowed to have more than one non-public class per source file, presumably the point is that developers are more likely to want to find the source code for a public class than a non-public one, since developers don’t work on the same package provided by others, so they don’t need to know the non-public classes. So the compiler should not worry too much about linking a non-public class because these are private to the package.

But we should always declare every class in its own file because it we will make the source short, simple, well organised and easy to understand.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java basics

Published at DZone with permission of Naresh Joshi, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}