Grund ist der Class-Loader.
Das ist übrigens eine ganz interessante Erläuterung. (Mal abgesehen davon, dass es ja der Compiler ist der meckert und nicht der ClassLoader!)
Schauen wir erst einmal, wieso diese Erläuterung nicht haltbar ist:
Wenn Wir uns das Beispiel von
@M.L. anschauen, dann sehen wir, dass es ja problemlos möglich ist, in einer Datei mehrere Top Level Klassen zu haben: Das kann dann auch kein Problem für den ClassLoader sein, denn der Compiler packt es ja in die entsprechenden .class Dateien - aus dem Beispiel wird also eine ObjektAnlegen.class und ProgrammStart.class.
=> Das, was für nicht "public" class geht, würde so natürlich prinzipiell auch für eine public class gehen.
Aber wir können weiter schauen, wieso es nicht erlaubt ist. Und da schauen wir in die JLS 7.6 und finden da:
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 class or interface is not found in a file under a name composed of the class or interface name plus an extension (such as .java or .jav) if either of the following is true:
- The class or interface is referred to by code in other ordinary compilation units of the package in which the class or interface is declared.
- The class or interface is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such class or interface per compilation unit. This restriction makes it easy for a Java compiler to find a named class or interface within a package. In practice, many programmers choose to put each class or interface in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.
Also ganz interessant: Es muss nicht so sein. "the host system may choose to enforce the restriction". Also wenn das host system das nicht erzwingen will, dann würde es auch funktionieren mit den zwei public class in einer Datei oder dass die Datei beliebig heisst.
Aber der Grund für diese Einschränkung wird auch direkt gegeben: Es soll dem Compiler leicht gemacht werden, die Klasse oder Interface in einem package zu finden. Also genau das, was Du umschrieben hast (ok, ClassLoader statt Compiler, aber das ändert ja nichts am eigentlichen Grund!)
Das einfach einmal als kleiner Exkursion, weil das halt ein Punkt ist, den ich recht interessant finde und es eine der ganz wenig Stellen ist, wo die JLS nicht exakt ist.