Warum können wir mit Java eine Klasse mit einem anderen Namen als dem Dateinamen kompilieren?

170

Ich habe eine Datei Test.javaund den folgenden Code darin.

public class Abcd
{
        //some code here

}

Jetzt wird die Klasse nicht kompiliert, aber wenn ich den publicModifikator entferne , wird sie gut kompiliert.

Was ist der Grund für Java, der es uns ermöglicht, einen Klassennamen zu kompilieren, der sich vom Dateinamen unterscheidet, wenn er nicht öffentlich ist?

Ich weiß, dass es sich um eine Anfängerfrage handelt, aber ich kann keine gute Erklärung finden.

user2434
quelle
28
Weil Java. (Weil es nicht öffentlich ist und nicht der gleichen Namenskonvention folgen muss. Darüber hinaus müssten Sie die Leute fragen, die es erfunden haben.)
Dave Newton
2
Ich bezweifle, dass es eine "gute Erklärung" gibt. Es war eine Anforderung für öffentliche Klassen, wurde jedoch für nicht öffentliche Klassen als unnötig erachtet.
Kayaman
2
Scheint wie eine ähnliche Frage: stackoverflow.com/questions/7633631/…
sanket
4
Warum so viele positive Stimmen für diese Frage, vor allem ihre doppelte Frage: stackoverflow.com/questions/7633631/…
GM Ramesh
2
@ Ramesh: Titel und Inhalt dieser Frage ist besser .. (als die anderen ähnlichen)
Jayan

Antworten:

325

Das Grundprinzip besteht darin, mehr als eine Klasse der obersten Ebene pro .javaDatei zuzulassen .

Viele Klassen - wie z. B. Ereignis-Listener - sind nur von lokalem Nutzen, und die frühesten Versionen von Java unterstützten keine verschachtelten Klassen. Ohne diese Lockerung der Regel "Dateiname = Klassenname" hätte jede dieser Klassen ihre eigene Datei benötigt, mit dem unvermeidlichen Ergebnis einer endlosen Verbreitung kleiner .javaDateien und der Streuung eng gekoppelten Codes.

Sobald Java verschachtelte Klassen einführte, nahm die Bedeutung dieser Regel erheblich ab. Heute können Sie viele hundert Java-Dateien durchgehen, ohne auf eine zu stoßen, die diese Vorteile nutzt.

Marko Topolnik
quelle
60
+1, dies liefert tatsächlich einen Grund , was die Frage ist.
Dave Newton
4
+1 insbesondere für die historischen Informationen - Ich vermute, dass es mit dem Aufkommen verschachtelter / anonymer Klassen viel sinnvoller wäre, nur eine Klasse der obersten Ebene pro Klasse zuzulassen, wenn jetzt dieselbe Entscheidung getroffen würde (ohne Rücksicht auf die Abwärtskompatibilität) Datei.
Michael Berry
1
@ berry120 Sehr wahrscheinlich, da diese Erlaubnis die Dateisuche beim Kompilieren erschwert.
Marko Topolnik
3
@Val Zu leugnen, dass andere Leute lieber einen Texteditor und CLI-Tools zum Entwickeln verwenden würden, weil die von Ihnen bevorzugte IDE existiert, ist genauso albern wie zu sagen, dass es keinen Sinn macht, IDEs zu erstellen, weil Sie ohne sie entwickeln können. Beide Ansätze werden von guten Entwicklern verwendet, um Qualitätscode zu erstellen. und das einzige, was kleiner ist als die Wahrscheinlichkeit, dass alle Entwickler einen von ihnen festlegen und Kumbaya singen, ist die Wahrscheinlichkeit, dass wir uns alle auf die beste Programmiersprache einigen.
Dan spielt
5
Die Kombination von Emacs (oder Vim, wählen Sie Ihr Gift) und den Unix-Shell-Dienstprogrammen ist möglicherweise nicht so einfach wie eine moderne IDE, und sie sind sicherlich schwieriger zu erlernen, haben aber zwei überwältigende Vorteile im Vergleich zu Jede IDE, die ich jemals ausprobiert habe: Sie stürzen nie ab, egal wie groß die Codebasis ist, und sie können mit meiner Eingabe Schritt halten.
zwol
80

Der Grund ist der gleiche wie für die Türschilder. Wenn eine Person offiziell im Büro wohnt (für öffentlich erklärt), muss ihr Name auf dem Türschild stehen. Wie "Alex Jones" oder "Detective Colombo". Wenn jemand nur den Raum besucht, mit einem Beamten spricht oder den Boden putzt, muss sein Name nicht offiziell an der Tür angebracht werden. Stattdessen kann an der Tür "Dienstprogramme" oder "Besprechungsraum" angezeigt werden.

Offizieller Name oder MyClass.java Besprechungsraum oder Test.java

exebook
quelle
4
Auf jeden Fall eine interessante Analogie; es könnte sogar noch besser sein, wenn ein wenig erklärt wird, wie es direkt zusammenhängt. Das OP könnte einige Schwierigkeiten haben, die Verbindung herzustellen (obwohl ich es perfekt verstehe)
Andrew Barber
4
@AndrewBarber Ich denke nicht, dass die Analogie wirklich passt, da sie nicht die eine öffentliche Klasse modelliert und die Datei mit mehreren paketprivaten Klassen teilt. Es ist wie auf der Türplatte mit der Aufschrift "Heather Santee, Manager", aber der Raum enthält tatsächlich Heather und ihre beiden Sekretärinnen.
Marko Topolnik
@ MarkoTopolnik Ich hätte mich nicht darauf einlassen sollen; Ich bin Klasse-A schrecklich in Analogien! ;)
Andrew Barber
@ AndrewBarber Ich wollte es trotzdem schreiben; Sie haben gerade einen Push gegeben :) Die Analogie drückt auch nicht die akuteste Besorgnis aus: Aufgrund dieser Funktion muss der Compiler alle Dateien analysieren, um alle Klassen zu ermitteln, in denen er sonst nur die Verzeichnisliste lesen und die Namen aller kennen könnte Top-Level-Klassen.
Marko Topolnik
@ AndrewBarber, die Analogie passt perfekt zur Idee des Verzeichnisses. In dem langen Korridor können Sie schnell eine Person finden, indem Sie nur auf die Türschilder blicken. Sie müssen nicht jeden Raum betreten und fragen.
Exebook
29

Die Java-Spezifikation besagt, dass Sie höchstens eine öffentliche Klasse pro Datei haben können. In diesem Fall sollte der Klassenname mit dem Dateinamen übereinstimmen. Alle nicht öffentlichen Klassen dürfen unabhängig vom Dateinamen einen beliebigen Namen haben.

Andrei Nicusan
quelle
20
Aber "was ist der Grund, warum Java dies zulässt"?
Marko Topolnik
@ MarkoTopolnik Weil es uns nicht hindert: D
Maroun
8
@MarounMaroun Aber was ist der Grund dafür, uns nicht zu verhindern?
Marko Topolnik
Mit @Marko Java können mehrere Klassen in derselben Datei definiert werden (solange nur eine davon öffentlich ist). Da alle Klassen innerhalb desselben Pakets einen anderen Namen haben müssen, gibt es keine andere Möglichkeit, als nicht öffentlichen Klassen zu erlauben, einen anderen Namen als den Dateinamen zu haben.
isnot2bad
2
Meine 2 Cent: Vielleicht wurde es so entwickelt, um Klassen innerhalb des Klassenpfads schneller zu lokalisieren. Mit dieser Konvention ist das Überprüfen der Dateinamen / -pfade für die Klassenerkennung ausreichend. Ohne diese Konvention muss der Klassenpfad-Klassenlader möglicherweise Dateien öffnen und analysieren, um Klassen zu finden
Andrei Nicusan
13

Ich denke, sie zuzulassen ist eine Voraussetzung für verschachtelte Klassen. Insbesondere anonyme Klassen reduzieren die Anzahl der erforderlichen Java-Dateien erheblich. Ohne Unterstützung dafür würden Sie viele Implementierungen von Schnittstellen für einzelne Methoden in ihren eigenen separaten Dateien von der Hauptklasse benötigen, in der sie verwendet werden. (Ich denke insbesondere an Action-Listener.)

Eine gute Erklärung aller verschachtelten Klassen finden Sie im Java-Lernprogramm für verschachtelte Klassen auf der Oracle-Website, das Beispiele für jede Klasse enthält . Es hat auch einen Grund, warum sie nützlich sind, den ich zitieren werde:

Warum verschachtelte Klassen verwenden?

Zu den zwingenden Gründen für die Verwendung verschachtelter Klassen gehören:

  • Es ist eine Möglichkeit, Klassen, die nur an einer Stelle verwendet werden, logisch zu gruppieren : Wenn eine Klasse nur für eine andere Klasse nützlich ist, ist es logisch, sie in diese Klasse einzubetten und die beiden zusammenzuhalten. Durch das Verschachteln solcher "Hilfsklassen" wird das Paket optimiert.

  • Es erhöht die Kapselung : Betrachten Sie zwei Klassen der obersten Ebene, A und B, wobei B Zugriff auf Mitglieder von A benötigt, die andernfalls als privat deklariert würden. Durch das Ausblenden von Klasse B in Klasse A können die Mitglieder von A als privat deklariert werden und B kann auf sie zugreifen. Außerdem kann B selbst vor der Außenwelt verborgen werden.

  • Dies kann zu besser lesbarem und wartbarem Code führen : Durch das Verschachteln kleiner Klassen in Klassen der obersten Ebene wird der Code näher an dem Ort platziert, an dem er verwendet wird.

(Hervorhebung von mir)

Ich bin mit Java-Spezifikationen in den frühen Tagen nicht vertraut, aber eine schnelle Suche zeigt, dass innere Klassen in Java 1.1 hinzugefügt wurden.

Joshua McKinnon
quelle
Was ist zu tun, wenn ein Typ nur innerhalb eines anderen Typs nützlich ist, Instanzen des ersteren Typs jedoch nicht mit Instanzen des letzteren verknüpft sind?
Supercat
Verschachtelte Klassen sind die Java 1.2-Methode zum Ausführen von Lambdas oder "First Class-Funktionen, wenn alles ein Objekt ist". Dies ändert sich in der 1.8-Syntax. Sie werden auch verwendet, wenn wir algebraische Datentypen im Java-Typsystem modellieren möchten.
Hawkeye
12

Ich sehe es umgekehrt. Der natürliche Zustand wäre, dass der Programmierer sowohl den Klassennamen als auch den Dateinamen unabhängig voneinander auswählt. Wahrscheinlich, um das Auffinden öffentlicher Klassen von außerhalb eines Pakets während der Kompilierung zu vereinfachen, gibt es eine besondere Einschränkung, dass sich eine öffentliche Klasse in einer Datei mit dem entsprechenden Namen befindet.

Patricia Shanahan
quelle
4

Beachten Sie, dass bei Java zwischen Groß- und Kleinschreibung unterschieden wird, das Dateisystem jedoch nicht. Wenn der Basisname der Datei "abcd" lautet, die Klasse jedoch "Abcd", entspricht dies der Regel in einem Dateisystem, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird? Sicherlich nicht, wenn auf eine Groß- und Kleinschreibung portiert wird.

Oder nehmen wir an, Sie haben zufällig eine Klasse namens ABCD und eine Klasse Abcd (lassen Sie uns nicht darauf eingehen, dass dies eine schlechte Idee ist: Es könnte passieren), und das Programm wird auf ein Dateisystem portiert, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. Jetzt müssen Sie nicht nur Dateien, sondern auch Klassen umbenennen, oops!

Oder was ist, wenn keine Datei vorhanden ist? Angenommen, Sie haben einen Java-Compiler, der Eingaben für Standardeingaben vornehmen kann. Also muss die Klasse "StandardInput" heißen?

Wenn Sie rational untersuchen, welche Auswirkungen es hat, dass Dateinamen Klassennamen folgen müssen, werden Sie feststellen, dass dies in mehrfacher Hinsicht eine schlechte Idee ist.

Kaz
quelle
Ich stimme dem zu, was Sie zu sagen haben, aber ich weiß nicht, dass es die Frage besonders beantwortet, außer vielleicht in dem Maße, in dem einige der Probleme, die sich aus der Namensarchitektur ergeben, dadurch gelöst werden könnten, dass nicht öffentliche Klassennamen von denen abweichen Dateinamen. BTW, im Hinblick auf die Groß- und Klein, wenn ich eine Sprache wurden ableiten, in jedem Bereich wurden Fooerklärt wurde, die Kennungen FOO, foo, fOousw. alle „nicht definiert“ werden würde , selbst wenn sie innerhalb der äußeren Bereiche vorhanden waren . Ein solches Design würde das Problem der Groß- und Kleinschreibung für Dateinamen beseitigen.
Supercat
3

Ein weiterer Punkt, auf den viele Antworten nicht hingewiesen haben, ist, dass publicdie JVM ohne die Deklaration niemals wissen würde, welche Hauptmethode der Klassen aufgerufen werden muss. Alle in einer Java-Datei deklarierten Klassen können Hauptmethoden haben, die Hauptmethode wird jedoch nur für die als öffentlich gekennzeichnete Klasse ausgeführt. HTH

happybuddha
quelle
0

Da eine Java-Datei mehr als eine Klasse enthalten kann, kann sie zwei Klassen in einer Java-Datei enthalten. Eine Java-Datei muss jedoch eine Klasse mit demselben Namen wie der Dateiname enthalten, wenn sie eine öffentliche Klasse enthält.

podongfeng
quelle
Nein, diese Regel gilt nur für öffentliche Klassen.
Deadboy