Dlaczego Java pozwala nam skompilować klasę o nazwie innej niż nazwa pliku?


170

Mam plik Test.javai następujący kod w nim.

public class Abcd
{
        //some code here

}

Teraz klasa się nie kompiluje, ale kiedy usuwam publicmodyfikator, kompiluje się dobrze.

Jaki jest powód, dla którego Java pozwala nam skompilować nazwę klasy, która różni się od nazwy pliku, gdy nie jest ona publiczna.

Wiem, że jest to pytanie dla początkujących, ale nie jestem w stanie znaleźć dobrego wyjaśnienia.


28
Ponieważ Java. (Ponieważ nie jest publiczny i nie musi przestrzegać tej samej konwencji nazewnictwa. Poza tym należałoby zapytać ludzi, którzy go wymyślili).
Dave Newton,

2
Wątpię, czy istnieje „dobre wyjaśnienie”. Był to wymóg na zajęciach publicznych, ale uznano go za niepotrzebny na zajęciach niepublicznych.
Kayaman

2
Wygląda na podobne pytanie: stackoverflow.com/questions/7633631/ ...
sanket

4
Skąd tyle głosów za to pytanie, przede wszystkim jego zduplikowane pytanie: stackoverflow.com/questions/7633631/…
GM Ramesh

2
@ Ramesh: tytuł i treść tego pytania jest lepsza ... (niż innych podobnych)
Jayan,

Odpowiedzi:


325

Uzasadnieniem jest zezwolenie na więcej niż jedną klasę najwyższego poziomu na .javaplik.

Wiele klas - takich jak nasłuchiwanie zdarzeń - jest używanych tylko lokalnie, a najwcześniejsze wersje języka Java nie obsługiwały klas zagnieżdżonych. Bez tego złagodzenia zasady „nazwa_pliku = nazwa klasy” każda taka klasa wymagałaby własnego pliku, czego nieuniknionym skutkiem byłoby niekończące się mnożenie małych .javaplików i rozpraszanie ściśle powiązanego kodu.

Gdy tylko Java wprowadziła klasy zagnieżdżone, znaczenie tej reguły znacznie zmalało. Dzisiaj możesz przeglądać setki plików Java, nigdy nie trafiając na taki, który to wykorzystuje.


60
+1, to faktycznie dostarcza powodu , o który jest pytanie.
Dave Newton,

4
+1 zwłaszcza dla informacji historycznych - podejrzewam, że wraz z pojawieniem się klas zagnieżdżonych / anonimowych, gdyby ta sama decyzja miała zostać podjęta teraz (nie dbając o kompatybilność wsteczną), o wiele bardziej sensowne byłoby dopuszczenie jednej klasy najwyższego poziomu na plik.
Michael Berry,

1
@ berry120 Całkiem prawdopodobne, ponieważ ten dodatek komplikuje wyszukiwanie plików podczas kompilacji.
Marko Topolnik

3
@Val Zaprzeczanie, że inni woleliby używać edytora tekstu i narzędzi CLI do programowania, ponieważ preferowane IDE istnieje, jest tak samo głupie, jak mówienie, że nie ma sensu tworzyć IDE, ponieważ można bez nich programować. Oba podejścia są używane przez dobrych programistów do tworzenia kodu wysokiej jakości; a jedyną rzeczą mniejszą niż szanse wszystkich programistów na załatwienie jednego z nich i śpiewanie kumbaya jest prawdopodobieństwo, że wszyscy zgodzimy się co do tego, jaki jest najlepszy język programowania.
Dan Is Fiddling By Firelight

5
Połączenie Emacsa (lub Vima, wybierz swoją truciznę) i narzędzi powłoki Unix być może nie jest tak dostępne na wyciągnięcie ręki jak nowoczesne IDE iz pewnością trudniej się ich nauczyć, ale mają dwie przytłaczające zalety w porównaniu z każde IDE, jakie kiedykolwiek próbowałem: nigdy się nie zawieszają, bez względu na to, jak ogromna jest baza kodu, i mogą nadążyć za moim pisaniem.
zwolni

80

Powód jest taki sam jak w przypadku płyt drzwiowych. Jeśli jakaś osoba oficjalnie przebywa w biurze (zadeklarowana jako publiczna), jej nazwisko musi znajdować się na przywieszce do drzwi. Na przykład „Alex Jones” czy „Detective Colombo”. Jeśli ktoś po prostu odwiedza pokój, rozmawia z urzędnikiem lub sprząta podłogę, jego nazwisko nie musi być oficjalnie umieszczane na drzwiach. Zamiast tego na drzwiach może znajdować się napis „Narzędzia” lub „Pokój konferencyjny”.

Oficjalna nazwa lub MyClass.java Sala konferencyjna lub Test.java


4
Zdecydowanie interesująca analogia; mogłoby być jeszcze lepiej, gdybyśmy trochę wyjaśnili, w jaki sposób ma to bezpośredni związek. OP może mieć pewne trudności z nawiązaniem połączenia (choć doskonale to rozumiem)
Andrew Barber

4
@AndrewBarber Nie sądzę, żeby ta analogia naprawdę pasowała, ponieważ nie modeluje jednej klasy publicznej, współużytkując plik z kilkoma klasami prywatnymi. Przypomina tabliczkę na drzwiach z napisem „Heather Santee, kierownik”, ale w pokoju w rzeczywistości jest Heather i jej dwie sekretarki.
Marko Topolnik

@MarkoTopolnik Nie powinienem był się w to angażować; Jestem okropny w klasie A w analogiach! ;)
Andrew Barber

@AndrewBarber W każdym razie chciałem to napisać; właśnie nacisnąłeś :) Analogia również nie wyraża najostrzejszego problemu: właśnie z powodu tej funkcji kompilator musi przeanalizować wszystkie pliki, aby znaleźć wszystkie klasy, w przeciwnym razie mógłby po prostu przeczytać listę katalogów i znać nazwy wszystkich zajęcia na najwyższym poziomie.
Marko Topolnik

@AndrewBarber, analogia doskonale wpisuje się w ideę katalogu, w długim korytarzu można szybko znaleźć osobę zerkając na tabliczki przy drzwiach, nie trzeba wchodzić do każdego pokoju i pytać.
exebook

29

Specyfikacja Java stwierdza, że ​​w jednym pliku można mieć tylko jedną klasę publiczną. W takim przypadku nazwa klasy powinna odpowiadać nazwie pliku. Wszystkie niepubliczne klasy mogą mieć dowolną nazwę, niezależnie od nazwy pliku.


20
Ale „jaki jest powód, dla którego Java pozwala nam na to”?
Marko Topolnik

@MarkoTopolnik Bo to nam nie przeszkadza: D
Maroun

8
@MarounMaroun Ale jaki jest powód, dla którego nas nie powstrzymuje?
Marko Topolnik

@Marko Java pozwala mieć wiele klas zdefiniowanych w tym samym pliku (o ile tylko jedna z nich jest publiczna). Ponieważ wszystkie klasy w tym samym pakiecie muszą mieć inną nazwę, nie ma innej opcji niż zezwolenie niepublicznym klasom na posiadanie innej nazwy niż nazwa pliku.
zły

2
Moje 2 centy: może został zaprojektowany w ten sposób, aby szybciej zlokalizować klasy w ścieżce klas. W tej konwencji inspekcja nazw / ścieżek plików jest wystarczająca do wykrywania klas. Bez tej konwencji, ładowarka klasa classpath może trzeba otworzyć i analizowania plików w celu znalezienia zajęcia
Andrei Nicusan

13

Myślę, że zezwolenie na nie jest warunkiem wstępnym dla klas zagnieżdżonych. W szczególności klasy anonimowe znacznie zmniejszają liczbę wymaganych plików .java. Bez obsługi tego potrzebowałbyś wielu implementacji interfejsu jednej metody w ich własnych oddzielnych plikach z głównej klasy, w której są używane. (Myślę w szczególności o odbiornikach akcji).

Jest to dobre wyjaśnienie wszystkich klas zagnieżdżonych w zagnieżdżone klasy samouczek Java na stronie internetowej firmy Oracle, która ma przykłady każdego z nich. Ma też powód, dla którego są przydatne, który zacytuję:

Dlaczego warto używać klas zagnieżdżonych?

Istotne powody używania klas zagnieżdżonych obejmują:

  • Jest to sposób na logiczne grupowanie klas, które są używane tylko w jednym miejscu : jeśli klasa jest przydatna tylko dla jednej innej klasy, logiczne jest osadzenie jej w tej klasie i trzymanie obu razem. Zagnieżdżanie takich „klas pomocniczych” sprawia, że ​​ich pakiet jest bardziej uproszczony.

  • Zwiększa hermetyzację : rozważ dwie klasy najwyższego poziomu, A i B, w których B potrzebuje dostępu do elementów członkowskich A, które w przeciwnym razie zostałyby uznane za prywatne. Ukrywając klasę B w klasie A, członkowie A mogą zostać uznani za prywatnych i B może uzyskać do nich dostęp. Ponadto samo B można ukryć przed światem zewnętrznym.

  • Może to prowadzić do bardziej czytelnego i łatwiejszego w utrzymaniu kodu : Zagnieżdżenie małych klas w klasach najwyższego poziomu umieszcza kod bliżej miejsca, w którym jest używany.

(podkreślenie moje)

Nie jestem zaznajomiony ze specyfikacją Javy na początku, ale szybkie wyszukiwanie pokazuje, że klasy wewnętrzne zostały dodane w Javie 1.1.


Co należy zrobić w przypadkach, gdy typ jest przydatny tylko w innym typie, ale wystąpienia pierwszego typu nie są powiązane z wystąpieniami drugiego typu?
supercat

Klasy zagnieżdżone to sposób w Javie 1.2 na wykonywanie lambd lub „funkcji pierwszej klasy, gdy wszystko jest obiektem”. To się zmienia w składni 1.8. Są również używane, gdy chcemy modelować algebraiczne typy danych w systemie typów Java.
hawkeye

12

Patrzę na to w drugą stronę. Naturalnym stanem rzeczy byłby wybór przez programistę zarówno nazwy klasy, jak i nazwy pliku niezależnie. Prawdopodobnie w celu uproszczenia wyszukiwania klas publicznych spoza pakietu podczas kompilacji, istnieje specjalne ograniczenie, aby klasa publiczna znajdowała się w pliku o odpowiedniej nazwie.


4

Zauważ, że Java rozróżnia wielkość liter, ale system plików nie musi. Jeśli podstawową nazwą pliku jest „abcd”, ale klasą jest „Abcd”, czy będzie to zgodne z regułą w systemie plików bez rozróżniania wielkości liter? Na pewno nie w przypadku przeniesienia do strony z rozróżnianiem wielkości liter.

Albo przypuśćmy, że przypadkowo masz klasę o nazwie ABCD i klasę Abcd (nie wmawiajmy sobie, że to zły pomysł: może się to zdarzyć), a program jest przeportowany na system plików bez rozróżniania wielkości liter. Teraz musisz nie tylko zmieniać nazwy plików, ale także klas, ups!

A co, jeśli nie ma pliku? Załóżmy, że masz kompilator Java, który może pobierać dane ze standardowego wejścia. Zatem klasa musi mieć nazwę „StandardInput”?

Jeśli racjonalnie zbadasz konsekwencje wymagania, aby nazwy plików występowały po nazwach klas, okaże się, że jest to zły pomysł z wielu powodów.


Zgadzam się z tym, co masz do powiedzenia, ale nie wiem, czy to szczególnie odpowiada na to pytanie, może poza tym, że być może w takim stopniu, w jakim niektóre problemy wynikające z architektury nazewnictwa można by złagodzić, dopuszczając inne niż publiczne nazwy klas nazwy plików. BTW, jeśli chodzi o sprawy wrażliwości, gdybym wynikające język, w każdym zakresie zostały Foouznano, identyfikatory FOO, foo, fOo, itd. Będą objęte „nieokreślony”, nawet jeśli istniały one w zakresach zewnętrznych. Taki projekt wyeliminowałby problem z rozróżnianiem wielkości liter w nazwach plików.
supercat

3

Inną kwestią, której brakowało w wielu odpowiedziach, jest to, że bez publicdeklaracji maszyna JVM nigdy nie dowiedziałaby się, która metoda klasy musi zostać wywołana. Wszystkie klasy zadeklarowane w jednym pliku .java mogą mieć wszystkie metody główne, ale główna metoda jest uruchamiana tylko na klasie oznaczonej jako publiczna. HTH


0

Ponieważ plik java może zawierać więcej niż jedną klasę, może mieć dwie klasy w jednym pliku java. Ale plik java musi zawierać klasę o takiej samej nazwie jak nazwa pliku, jeśli zawiera klasę publiczną.


Nie, ta zasada dotyczy tylko zajęć publicznych.
deadboy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.