Does Java allow two classes in one file?

Short answer will be: no, it does not for public classes. But yes, it does for non-public ones.

According to JavaSE7 specification http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.6  it's up to compiler to allow or deny multiple public classes in one 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).

In practise, all compilers I ever met applied this restriction. The rule is: one public class – one .java file (which is a compilation unit)  with the same name. 

For example, let's put two public classes in one file and we'll get compilation error:

File: OneClass.java
 
/**
* Compilation error:
* The public type SecondClass should be defined in it's own file
*/

package classesTest1;

 

public class OneClass {

}

public class SecondClass {

}

 

 

But if we place any number of non public classes in single file, the code will be compiled:

File: OneClass.java

 

/**
* It's Ok, no errors
*/

package classesTest1;
 
class OneClass {
 
}
 
class SecondClass {
 
}
 
class ThirdClass {
 
}

 

Public class should be placed in a file with the same name. But we can place non-public classes  across any .java files:

File: OneClass.java

/**
* It's Ok, no errors
*/

package classesTest1;
 
class ClassWithDifferentFromFileName {
 
}

 

At the end of our story let's talk about nested classes. It's a different case. Nested classes can be named and placed without restrictions:

File: Outer.java 

package javaProject1;
/**
* Nested classes are Ok, no compilation errors produced
*/
class Outer {

public class Inner1 {

}

public class Inner2 {

}

public class Inner3 {
{
}

}

 

 

Some misunderstanding still exists in my mind. I understand that it's easier for compiler to find public class inside related compilation unit – .java file with the same name. But why it's not the same for non-public classes? It looks like some historical stuff from old Java.

 

Leave a Reply

Your email address will not be published.