Dlaczego każda klasa publiczna jest w osobnym pliku?

Niedawno zacząłem uczyć się Javy i okazało się bardzo dziwne, że każda klasa Javy musi być zadeklarowana w osobnym pliku. Jestem programistą C# i C# nie wymusza takiego ograniczenia.

Dlaczego Java to robi? Czy rozważano jakiś projekt?

Edycja (na podstawie kilku odpowiedzi):

Dlaczego Java nie usuwa tego ograniczenia w erze IDE? To nie złamie żadnego istniejącego kodu (a może będzie?).

Author: Peter Mortensen, 2009-08-23

12 answers

Zgodnie ze specyfikacją języka Java, wydanie trzecie :

To ograniczenie oznacza, że na jednostkę kompilacji musi być co najwyżej jeden taki typ. to ograniczenie ułatwia kompilatorowi języka programowania Java lub implementacji wirtualnej maszyny Java znalezienie nazwanej klasy w pakiecie ; na przykład kod źródłowy publicznego typu wet.zębatka.Ropucha znajduje się w pliku Ropucha.java w katalogu wet/sprocket oraz odpowiedni kod obiektowy zostanie znaleziony w pliku Toad.klasa w tym samym katalogu.

Nacisk jest mój.

Wygląda na to, że w zasadzie chcieli przetłumaczyć separator katalogów systemu operacyjnego na kropki dla przestrzeni nazw i vice versa.

Więc tak, to był jakiś projekt.

 31
Author: Mark Rushakoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-23 14:51:55

Właśnie wziąłem rozwiązanie C# i zrobiłem to (usunąłem każdy plik, który miał wiele klas publicznych w nich) i rozdzieliłem je na poszczególne pliki, a to znacznie ułatwiło życie.

Jeśli masz kilka klas publicznych w pliku, masz kilka problemów:

  1. Jak nazwiesz plik? Jedna z klas publicznych? Inne nazwisko? Ludzie mają wystarczająco dużo problemów wokół złej organizacji kodu rozwiązania i konwencji nazewnictwa plików, aby mieć jeden dodatkowy problem.

  2. Ponadto, gdy przeglądasz Eksplorator plików / projektów, dobrze jest, że rzeczy nie są ukryte. Na przykład widzisz jeden plik i drill down i jest 200 klas wszystkie mushed razem. Jeśli masz jeden plik jednej klasy, możesz lepiej zorganizować swoje testy i poczuć strukturę i złożoność rozwiązania.

Myślę, że Java ma rację.

 56
Author: leora,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 03:46:05

From Thinking in Java

:

Na Jednostkę kompilacji (plik) może być tylko jedna klasa publiczna.
Chodzi o to, że każda jednostka kompilacji ma jeden publiczny interfejs reprezentowany przez tę klasę publiczną . Może mieć tyle wspierających "przyjaznych" klas, ile chcesz. Jeśli w jednostce kompilacji znajduje się więcej niż jedna publiczna Klasa, kompilator wyświetli komunikat o błędzie.


Ze specyfikacji (7.2.6)

Gdy pakiety są przechowywane w systemie plików (?7.2.1), system hosta może wybrać, aby wymusić ograniczenie, że jest to błąd w czasie kompilacji, jeśli Typ nie zostanie znaleziony w pliku pod nazwą złożoną z nazwy typu i rozszerzenia (np.java lub .jav) jeżeli którakolwiek z poniższych wartości jest prawdziwa :

  • typ jest określany kodem w innych jednostkach kompilacji pakietu, w którym typ jest zadeklarowany.
  • typ jest zadeklarowana jako publiczna (i dlatego jest potencjalnie dostępna z kodu w innych pakietach).
  • to ograniczenie zakłada, że na jednostkę kompilacji musi być co najwyżej jeden taki typ.
  • to ograniczenieułatwia kompilatorowi języka programowania Java lub implementacji wirtualnej maszyny Java znalezienie nazwanej klasy w pakiecie ; na przykład kod źródłowy publicznego typu wet.zębatka.Ropucha znajduje się w pliku Ropucha.java w katalog wet / sprocket, a odpowiadający mu kod obiektowy zostanie znaleziony w pliku Toad.klasa w tym samym katalogu.

W skrócie: może to być znalezienie klas bez konieczności ładowania wszystkiego na swojej ścieżce klasowej.

W przeciwieństwie do innych języków, w których istnieje wiele języków, w których istnieje wiele języków, w których istnieje wiele języków, w których istnieje wiele języków.]} W praktyce jednak jest to egzekwowane w tak wiele platform i opiera się na tak wielu narzędziach i IDE, że nie widzę żadnego "systemu hosta" wybierając nie egzekwować to ograniczenie.

From " Once upon an Oak ..."

Jest to dość oczywiste - jak większość rzeczy jest, gdy znasz powody projektowe - kompilator musiałby wykonać dodatkowe przejście przez wszystkie jednostki kompilacji (.pliki java), aby dowiedzieć się, jakie klasy są gdzie, a to sprawi, że kompilacja nawet wolniej.

(Uwaga:

The Oak Language Specification for Oak version 0.2 (PostScript document): Oak była oryginalną nazwą tego, co jest obecnie powszechnie znane jako Java, a ten podręcznik jest najstarszym podręcznikiem dostępnym dla Oak (tj. Java).
Aby dowiedzieć się więcej o początkach Javy, zajrzyj do The Green Project i Java(TM) Technology: an Early History
)

 17
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-25 06:52:07

To po prostu uniknąć nieporozumień w tym sensie, że Java została stworzona z myślą o prostocie z perspektywy dewelopera. Twoje "podstawowe" klasy są twoimi klasami publicznymi i są łatwe do znalezienia (przez człowieka), jeśli znajdują się w pliku o tej samej nazwie i w katalogu określonym przez pakiet klasy.

Należy pamiętać, że język Java został opracowany w połowie lat 90., w czasach, zanim IDEs zrobił nawigację kodu i wyszukiwanie bryza .

 6
Author: oxbow_lakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-23 14:35:07

Jeśli klasa jest używana tylko przez jedną inną klasę, Uczyń ją prywatną klasą wewnętrzną. W ten sposób Masz wiele klas w pliku.

Jeśli klasa jest używana przez wiele innych klas, którą z tych klas umieścisz w tym samym pliku? Wszystkie trzy? Skończyłbyś mając wszystkie zajęcia w jednym pliku...

 3
Author: Zed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-23 14:54:00

Tak właśnie zdecydowali się projektanci języka. Myślę, że głównym powodem była optymalizacja przejść kompilatora-kompilator nie musi odgadywać ani analizować plików, aby zlokalizować publiczne klasy. Myślę, że to właściwie dobra rzecz, sprawia, że pliki kodu są znacznie łatwiejsze do znalezienia i zmusza cię do trzymania się z dala od wkładania zbyt wielu plików do jednego pliku. Podoba mi się również to, jak Java zmusza cię do umieszczania plików kodu w tej samej strukturze katalogów co pakiet-ułatwia to zlokalizuj dowolny plik kodu.

 3
Author: Andy White,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-25 05:46:25

Dlaczego java nie usuwa tego ograniczenia w erze IDE? To nie złamie żadnego istniejącego kodu (a może będzie?).

Teraz cały kod jest jednolity. Kiedy zobaczysz plik źródłowy, wiesz, czego się spodziewać. to samo dotyczy każdego projektu. Jeśli java usunęłaby tę konwencję, musisz ponownie nauczyć się struktury kodu dla każdego projektu, nad którym pracujesz, gdzie jak teraz nauczysz się go raz i zastosujesz wszędzie. Nie powinniśmy ufać IDE za wszystko.

 2
Author: Hamza Yerlikaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-23 15:55:27

Technicznie legalne jest posiadanie wielu klas najwyższego poziomu Javy w jednym pliku. Jest to jednak uważane za złą praktykę, a wiele narzędzi Java (w tym IDE) nie działa, jeśli to zrobisz.

JLS mówi tak:

Gdy pakiety są przechowywane w pliku system (§7.2.1), system hosta może wybrać, aby wyegzekwować ograniczenie , które jest to błąd w czasie kompilacji, jeśli Typ nie znajduje się w pliku pod nazwą składa się z nazwy typu plus rozszerzenie (np.java lub .jav) jeśli jedno z poniższych jest prawdziwe:

  • typ jest określany kodem w innych jednostkach kompilacji pakietu, w którym typ jest zadeklarowany.
  • typ jest zadeklarowany jako publiczny (i dlatego jest potencjalnie dostępny z kodu w innych pakietach).

Zwróć uwagę na użycie may w tekście JLS. To mówi, że kompilator może odrzucić to jako nieprawidłowe lub nie. To nie jest dobra sytuacja, jeśli jesteś próba zbudowania kodu Javy tak, aby był przenośny na poziomie kodu źródłowego . Tak więc, nawet jeśli wiele klas w jednym pliku źródłowym działa na twojej platformie programistycznej, jest to zła praktyka.

Rozumiem, że to "pozwolenie na odrzucenie" jest decyzją projektową, która ma w części ułatwić implementację Javy na szerszej gamie platform. Jeśli (odwrotnie) JLS wymagał od wszystkich kompilatorów obsługi plików źródłowych zawierających wiele klas, tam byłyby to problemy koncepcyjne implementujące Javę na platformie, która nie była oparta na systemie plików.

W praktyce doświadczeni programiści Javy w ogóle nie przegapią możliwości zrobienia tego. Modularyzacja i ukrywanie informacji są lepiej wykonywane przy użyciu odpowiedniej kombinacji pakietów, modyfikatorów dostępu do klas i klas wewnętrznych lub zagnieżdżonych.

 2
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-21 07:02:31

Tak naprawdę nie jest to odpowiedź na pytanie, ale punkt danych.

I greped nagłówki mojej osobistej biblioteki C++ utilty (można dostać go samodzielnie z tutaj) i prawie wszystkie pliki nagłówkowe, które faktycznie deklarują klasy (niektóre tylko deklarują wolne funkcje) deklarują więcej niż jedną klasę. Lubię myśleć o sobie jako o całkiem niezłym projektancie C++ (choć Biblioteka jest trochę zatłoczona miejscami - jestem jej jedynym użytkownikiem), więc proponuję, aby Dla C++ przynajmniej kilka klasy w tym samym pliku są normalne, a nawet dobre praktyki.

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-23 17:05:59

Pozwala na prostsze heurystyki wychodzenia z Foobara.Klasa do Foobara.java.

Jeśli Foobar może znajdować się w dowolnym pliku Javy, masz problem z mapowaniem, co może ostatecznie oznaczać, że musisz wykonać pełne skanowanie wszystkich plików Javy, aby zlokalizować definicję klasy.

Osobiście uważam, że jest to jedna z dziwnych reguł, które w połączeniu skutkują tym, że aplikacje Java mogą rosnąć bardzo duże i nadal być solidne.

 1
Author: Thorbjørn Ravn Andersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-24 10:59:51

W jednym pliku może być wiele klas publicznych. Jednak klasa najwyższego poziomu na plik. W pliku może być tyle publicznych klas wewnętrznych/zagnieżdżonych, ile chcesz.

Myślę, że podoba Ci się ten link - czy plik java może mieć więcej niż jedną klasę?

 1
Author: adatapost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:21

W rzeczywistości jest to opcjonalne ograniczenie zgodnie ze specyfikacją języka Java (sekcja 7.6, Strona nr 209), a następnie Oracle Java compiler jako obowiązkowe ograniczenie. Zgodnie ze specyfikacją języka Java,

Gdy pakiety są przechowywane w systemie plików (§7.2.1), system hosta może wyegzekwować ograniczenie, że jest to błąd w czasie kompilacji jeśli Typ nie zostanie znaleziony w pliku pod nazwą złożoną z typu nazwa plus rozszerzenie (np.java lub .jav) jeżeli którekolwiek z następujące jest prawdziwe:

  • typ jest określany kodem w innych jednostkach kompilacji pakietu, w którym typ jest zadeklarowany.
  • typ jest zadeklarowany jako publiczny (i dlatego jest potencjalnie dostępny z kodu w innych pakietach).

To ograniczenie zakłada, że musi być co najwyżej jeden taki typ na Jednostka kompilacyjna. Ograniczenie to ułatwia kompilatorowi Javy aby znaleźć nazwaną klasę w pakiecie.

W praktyce wielu programistów decyduje się umieścić każdą klasę lub interfejs wpisz we własnej jednostce kompilacji, niezależnie od tego, czy jest ona Publiczna czy o których mowa kodem w innych jednostkach kompilacji.

Na przykład, kod źródłowy dla typu publicznego wet.zębatka.Toad would / align = "left" / java w katalogu stron internetowych / strona 1 odpowiedni kod obiektowy zostanie znaleziony w pliku Toad.klasa w ten sam katalog.

Aby uzyskać bardziej jasny obraz, wyobraź sobie, że istnieją dwie publiczne klasy publiczna Klasa A i publiczna Klasa B w tym samym pliku źródłowym, a klasa ma odniesienie do jeszcze nie skompilowanej klasy B. i kompilujemy (compiling-linking-loading) klasę A teraz, gdy linkujemy do klasy B kompilator będzie zmuszony zbadać każdą *.plików java w bieżącym pakiecie, ponieważ Klasa B nie ma specyficznych B.java plik. Więc w powyższym przypadku, jest trochę czasochłonne dla kompilatora, aby znaleźć, która klasa leży pod jakim plikiem źródłowym i w która klasa leży główną metodą. Tak więc powodem utrzymywania jednej klasy publicznej na plik źródłowy jest przyspieszenie procesu kompilacji, ponieważ umożliwia bardziej efektywne wyszukiwanie źródeł i skompilowanych plików podczas łączenia (instrukcje importu). Chodzi o to, że jeśli znasz nazwę klasy, wiesz, gdzie powinna ona być znaleziona dla każdego wpisu classpath i nie będzie wymagane indeksowanie.

A także jak tylko uruchomimy naszą aplikację JVM domyślnie szuka klasy publicznej (ponieważ nie ma ograniczeń i może być dostępny z dowolnego miejsca), a także szuka public static void main(String args[]) w tej klasie publicznej. Klasa publiczna działa jako klasa początkowa, z której uruchamiana jest instancja JVM dla aplikacji (programu) Java. Więc kiedy podajemy więcej niż jedną publiczną klasę w programie, kompilator zatrzymuje cię przez wyrzucenie błędu. To dlatego, że później nie możemy pomylić JVM, która klasa ma być jego klasą początkową, ponieważ tylko jedna klasa publiczna z public static void main(String args[]) jest klasą początkową dla JVM.

Możesz przeczytać więcej na dlaczego pojedynczy plik źródłowy Javy nie może mieć więcej niż jednej klasy publicznej

 1
Author: Naresh Joshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-04 05:01:30