Dlaczego plik źródłowy Java nosi nazwę zawartej w nim klasy publicznej?

14

Jestem początkującym uczącym się języka Java. W Javie każdy plik źródłowy musi zawierać klasę publiczną, a ten plik źródłowy powinien mieć taką samą nazwę jak ta klasa publiczna. Ponadto żaden plik źródłowy nie może zawierać dwóch klas publicznych. Dlaczego to ograniczenie?

użytkownik
źródło
4
Bez tych szczegółów jest to historyczny artefakt projektowania inżynierii Java. Ostatnio zaprojektowane języki, takie jak C #, choć podobne do Java, nie mają tego ograniczenia.
gahooa
13
Czy to nie egzekwowanie najlepszych praktyk? Myślałem, że to jedyny powód. W języku C # nie masz tego ograniczenia na poziomie technicznym, ale nadal StyleCop będzie narzekać, jeśli nazwa pliku i nazwa klasy nie będą zgodne lub jeśli masz kilka klas w tym samym pliku. Program Visual Studio również mocno zachęca do relacji klasa-plik (pomyśl o diagramach klas, które tworzą pliki dla Ciebie, lub gdy zmienisz nazwę pliku .cs, Visual Studio zapyta, czy chcesz również zmienić nazwę klasy).
Arseni Mourzenko
W skompilowanym języku w starym stylu linker znajduje wszystkie odniesienia i symbole zewnętrzne. Ale Java nie jest połączona - jeśli chcesz, możesz załadować słoiki w czasie wykonywania. Bez kroku łączenia próba mapowania nazw klas do lokalizacji w ścieżce klasy jest znacznie szybsza, jeśli wiesz, jakiej nazwy pliku szukać.
Paul Tomblin
4
@ gahooa to nie jest artefakt projektowy, to celowa decyzja projektowa. To znacznie ułatwia wiele rzeczy.
1
Co z używaniem grep ?
użytkownik

Odpowiedzi:

19

W jednym ze swoich biuletynów specjalistów Java, Heinz Kabutz przegląda specyfikacje języka dębowego . On pisze:

Dlaczego każda klasa publiczna znajduje się w osobnym pliku? (Sekcja 1)

To pytanie często zadawano mi podczas moich kursów. Do tej pory nie miałem dobrej odpowiedzi na to pytanie. W części 1 czytamy: „Chociaż każda jednostka kompilacji Oak może zawierać wiele klas lub interfejsów, najwyżej jedna klasa lub interfejs na jednostkę kompilacji może być publiczny”.

Na pasku bocznym wyjaśniono, dlaczego: „To ograniczenie nie jest jeszcze egzekwowane przez kompilator, chociaż jest konieczne do skutecznego importowania pakietów”

Jest to dość oczywiste - jak większość rzeczy, kiedy znasz już powody projektowania - kompilator musiałby wykonać dodatkowe przejście przez wszystkie jednostki kompilacji (pliki .java), aby dowiedzieć się, gdzie są klasy, a to spowodowałoby, że kompilacja byłaby jeszcze wolniejsza .

http://www.javaspecialists.eu/archive/Issue055.html

Landei
źródło
1
Czy kompilacja jest nieznacznie szybsza? Naprawdę? Nie dlatego, że kod jest znacznie bardziej zorganizowany? Bardzo wątpię, że to poprawna odpowiedź.
BlueRaja - Danny Pflughoeft
1
@ BlueRaja-DannyPflughoeft W 1998 roku jestem pewien, że zrobiło to znacznie większą różnicę
TheLQ
8

Powody, dla których mogę wymyślić

  • Ułatwia znalezienie innych klas dla kompilatora na początku, ponieważ nie musi on przeszukiwać wszystkich potencjalnie tysięcy plików klas w poszukiwaniu losowej klasy publicznej, może po prostu przejść do pliku.
    • To prawdopodobnie nie ma już znaczenia, ale właśnie rozpoczęło się wczesną konwencję, która nigdy się nie zmieniła
  • Podczas kompilacji zmiana pliku wpływa tylko na ten plik. Jeśli istnieje wiele klas, wszystko musi zostać ponownie skompilowane
  • Najlepsza praktyka - posiadanie wielu klas publicznych w tym samym pliku powoduje zamieszanie. Celem plików jest uporządkowanie kodu źródłowego, celem folderów jest uporządkowanie plików. Jeśli wszystkie klasy danego pakietu znajdują się w pojedynczym super pliku 100 MB, utraciłeś wszystkie zalety i nie zyskałeś żadnej korzyści z plików (plus dodatkowe przyspieszenie bólu głowy podczas edycji)
TheLQ
źródło
1
Klasy i interfejsy niekoniecznie reprezentują najbardziej naturalny poziom podziału kodu źródłowego. Posiadanie wielu tysięcy wierszy kodu w jednym pliku jest niewygodne, ale nie jest też tak, że 100 wierszy „rzeczywistej” treści (z wyłączeniem komentarzy lub zduplikowanych dyrektyw kompilatora) nie ma też w kilku plikach źródłowych. Zastanawiam się, jak by to działało, gdyby plik nazwany dla tego typu musiał albo zawierać definicję, albo identyfikować plik, który ją zawiera?
supercat