Почему Java позволяет нам компилировать класс с именем, отличным от имени файла?

170

У меня есть файл Test.javaи следующий код внутри него.

public class Abcd
{
        //some code here

}

Теперь класс не компилируется, но когда я удаляю publicмодификатор, он компилируется нормально.

В чем причина того, что Java позволяет нам компилировать имя класса, которое отличается от имени файла, когда оно не является публичным.

Я знаю, что это вопрос новичка, но я не могу найти хорошего объяснения.

user2434
источник
28
Потому что Java. (Потому что он не является публичным и не должен следовать одному и тому же соглашению об именах. Кроме того, вам нужно будет спросить людей, которые его изобрели.)
Дейв Ньютон,
2
Я сомневаюсь, что есть «хорошее объяснение». Это было требование для публичных классов, но оно считалось ненужным для непубличных классов.
Каяман
2
Похоже на аналогичный вопрос: stackoverflow.com/questions/7633631/…
sanket
4
Почему так много голосов за этот вопрос, прежде всего его повторяющийся вопрос: stackoverflow.com/questions/7633631/…
GM Ramesh
2
@ Рамеш: название и содержание этого вопроса лучше .. (чем другие подобные)
Jayan

Ответы:

325

Обоснование заключается в том, чтобы разрешить более одного класса верхнего уровня на .javaфайл.

Многие классы, такие как прослушиватели событий, имеют локальное использование, и самые ранние версии Java не поддерживали вложенные классы. Без этого ослабления правила «имя файла = имя класса» каждому такому классу потребовался бы собственный файл с неизбежным результатом бесконечного распространения небольших .javaфайлов и разброса тесно связанного кода.

Как только Java представила вложенные классы, важность этого правила значительно уменьшилась. Сегодня вы можете просматривать сотни файлов Java, не выбирая тот, который использует его.

Марко Топольник
источник
60
+1, это фактически обеспечивает причину , которая является вопросом.
Дейв Ньютон
4
+1 для исторической информации, особенно - я подозреваю, что с появлением вложенных / анонимных классов, если бы то же самое решение было принято сейчас (не заботясь о обратной совместимости), было бы гораздо разумнее просто разрешить один класс верхнего уровня на файл.
Майкл Берри
1
@ berry120 Вполне возможно, потому что этот допуск усложняет поиск файлов при компиляции.
Марко Топольник
3
@Val. Отрицать, что другие люди предпочитают использовать текстовый редактор и инструменты CLI для разработки, потому что вы предпочитаете IDE, это так же глупо, как говорить, что нет смысла создавать IDE, потому что вы можете заниматься разработкой без них. Оба подхода используются хорошими разработчиками для создания качественного кода; и единственное, что меньше, чем шансы всех разработчиков выбрать одного из них и спеть kumbaya, - это шансы, что мы все согласимся с тем, какой язык программирования является лучшим.
Дэн возится с Firelight
5
Сочетание Emacs (или Vim, выбери свой яд) и утилит оболочки Unix, возможно, не так удобно, как современная IDE, и их, безусловно, сложнее освоить, но у них есть два неоспоримых преимущества по сравнению с все IDE, которые я когда-либо пробовал: они никогда не падают, независимо от того, насколько велика база кода, и они могут не отставать от моей типизации.
Звол
80

Причина та же, что и для дверных табличек. Если какой-либо человек официально проживает в офисе (объявлен публичным), его / ее имя должно быть на дверной бирке. Как «Алекс Джонс» или «Детектив Коломбо». Если кто-то просто заходит в комнату, разговаривает с чиновником или убирает пол, его имя не обязательно должно быть официально указано на двери. Вместо этого на двери можно прочитать «Утилиты» или «Комната переговоров».

Официальное имя или MyClass.java Конференц-зал или Test.java

exebook
источник
4
Определенно интересная аналогия; могло бы быть даже лучше с небольшим объяснением того, как это непосредственно связано. У ОП могут возникнуть трудности с установлением соединения (хотя я это прекрасно понимаю)
Эндрю Барбер,
4
@AndrewBarber Я не думаю, что аналогия действительно подходит, поскольку она не моделирует один открытый класс, разделяя файл с несколькими закрытыми для пакета классами. Это похоже на табличку на двери с надписью «Хизер Санти, менеджер», но комната на самом деле содержит Хизер и ее двух секретарей.
Марко Топольник
@MarkoTopolnik Я не должен был вмешиваться в это; Я ужасный класс по аналогии! ;)
Эндрю Барбер
@AndrewBarber Я все равно хотел написать это; Вы только что подтолкнули :) Аналогия также не в состоянии выразить самую острую озабоченность: именно благодаря этой функции компилятор должен проанализировать все файлы, чтобы обнаружить все классы, в противном случае он мог бы просто прочитать список каталогов и узнать имена всех занятия на высшем уровне.
Марко Топольник
@AndrewBarber, аналогия идеально подходит к идее каталога, в длинном коридоре вы можете быстро найти человека, просто взглянув на дверные таблички, вам не нужно входить в каждую комнату и спрашивать.
exebook
29

Спецификация Java гласит, что вы можете иметь только один открытый класс на файл. В этом случае имя класса должно соответствовать имени файла. Все непубличные классы могут иметь любое имя независимо от имени файла.

Андрей Никусан
источник
20
Но «в чем причина того, что Java позволяет» нам это?
Марко Топольник
@MarkoTopolnik Потому что это не мешает нам: D
Maroun
8
@MarounMaroun Но что за причины не мешают нам?
Марко Топольник
@Marko Java позволяет иметь несколько классов, определенных в одном файле (если только один из них является общедоступным). Поскольку все классы в одном и том же пакете должны иметь разные имена, нет другого выбора, кроме как разрешить непубличным классам иметь имя, отличное от имени файла.
isnot2bad
2
Мои 2 цента: возможно, это было разработано таким образом для более быстрой локализации классов внутри classpath. С этим соглашением, проверка имен файлов / путей достаточно для обнаружения класса. Без этого соглашения загрузчику классов classpath может понадобиться открывать и анализировать файлы, чтобы найти классы
Андрей Никусан
13

Я думаю, что разрешение их является обязательным условием для вложенных классов. В частности, анонимные классы значительно сокращают количество необходимых файлов .java. Без поддержки этого вам потребовалось бы множество реализаций интерфейса одного метода в их отдельных файлах от основного класса, в котором они используются. (Я имею в виду слушателей действия в частности)

Хорошее объяснение всех вложенных классов содержится в руководстве Java « Вложенные классы» на веб-сайте Oracle, в котором приведены примеры каждого из них. У этого также есть причина, они полезны, который я процитирую:

Зачем использовать вложенные классы?

Необоснованные причины использования вложенных классов:

  • Это способ логически сгруппировать классы, которые используются только в одном месте : если класс полезен только для одного другого класса, то логично встраивать его в этот класс и сохранять их вместе. Вложение таких «вспомогательных классов» делает их пакет более упорядоченным.

  • Это увеличивает инкапсуляцию : рассмотрим два класса верхнего уровня, A и B, где B необходим доступ к членам A, которые в противном случае были бы объявлены закрытыми. Скрывая класс B в классе A, члены A могут быть объявлены частными, и B может получить к ним доступ. Кроме того, сам B может быть скрыт от внешнего мира.

  • Это может привести к более удобочитаемому и поддерживаемому коду : вложение небольших классов в классы верхнего уровня помещает код ближе к месту его использования.

(акцент мой)

Я не был знаком с Java-спецификацией в ранние годы, но быстрый поиск показывает, что в Java 1.1 были добавлены внутренние классы.

Джошуа Маккиннон
источник
Что делать в тех случаях, когда тип полезен только внутри другого типа, но экземпляры первого типа не связаны с экземплярами второго типа?
суперкат
Вложенные классы - это способ выполнения лямбды в Java 1.2 или «Функции первого класса, когда все является объектом». Это меняется в 1.8 Синтаксис. Они также используются, когда мы хотим моделировать алгебраические типы данных в системе типов Java.
Соколиный глаз
12

Я смотрю на это с другой стороны. Для программиста естественным было бы выбирать и имя класса, и имя файла независимо. Вероятно, чтобы упростить поиск открытых классов извне пакета во время компиляции, существует специальное ограничение, согласно которому открытый класс должен находиться в файле с соответствующим именем.

Патриция Шанахан
источник
4

Обратите внимание, что в Java учитывается регистр, но файловая система не обязательна. Если базовое имя файла - «abcd», а класс - «Abcd», будет ли это соответствовать правилу в файловой системе без учета регистра? Конечно, не при переносе на регистр.

Или предположим, что у вас есть класс с именем ABCD и класс Abcd (давайте не вдаваться в плохую идею: это может произойти), и программа портирована на нечувствительную к регистру файловую систему. Теперь вам нужно переименовывать не только файлы, но и классы, упс!

Или что если нет файла? Предположим, у вас есть компилятор Java, который может принимать входные данные при стандартном вводе. Так тогда класс должен быть назван "StandardInput"?

Если вы рационально исследуете, что имена файлов должны следовать за именами классов, вы обнаружите, что это плохая идея по нескольким причинам.

Kaz
источник
Я согласен с тем, что вы хотите сказать, но я не знаю, что именно он отвечает на этот вопрос, разве что, возможно, в той степени, в которой некоторые из проблем, возникающих из-за архитектуры именования, могут быть облегчены, если позволить непубличным именам классов отличаться от имена файлов. Кстати, что касается случая чувствительности, если я получение языка, в любом объеме были Fooбыло объявлено, идентификаторы FOO, foo, fOoи т.д. бы все «не определены» , даже если бы они существовали в пределах внешних областей. Такой дизайн устранит проблему чувствительности к регистру имен файлов.
суперкат
3

Также еще один момент, на который многие пропущенные ответы указывают, заключается в том, что без publicобъявления JVM никогда не узнает, какой основной метод классов необходимо вызвать. Все классы, объявленные в одном файле .java, могут иметь методы main, но метод main запускается только для класса, помеченного как public. НТН

happybuddha
источник
0

Поскольку файл Java может содержать более одного класса, он может иметь два класса в одном файле Java. Но файл Java должен содержать класс с тем же именем, что и имя файла, если он содержит открытый класс.

podongfeng
источник
Нет, это правило применимо только для публичных классов.
Deadboy