Будет ли компилироваться следующий код, если оба класса объявлены в тестовом файле Java

Обновлено: 02.07.2024

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

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

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

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

Потому что Java. (Потому что он не является общедоступным и не должен следовать тому же соглашению об именах. Кроме того, вам нужно спросить людей, которые его придумали.)

Сомневаюсь, что есть "хорошее объяснение". Это было требованием для общедоступных классов, но было сочтено ненужным для закрытых классов.

8 ответов 8

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

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

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

+1 особенно за историческую информацию - я подозреваю, что с появлением вложенных/анонимных классов, если бы такое же решение было принято сейчас (не заботясь об обратной совместимости), было бы гораздо разумнее просто разрешить один верхний класс уровня для каждого файла.

@Val Отрицать, что другие люди предпочли бы использовать текстовый редактор и инструменты CLI для разработки, потому что вы предпочитаете IDE, так же глупо, как говорить, что нет смысла создавать IDE, потому что вы можете заниматься разработкой без них. Оба подхода используются хорошими разработчиками для создания качественного кода; и единственное, что меньше, чем вероятность того, что все разработчики выберут одного из них и будут петь кумбая, — это вероятность того, что мы все согласимся с тем, какой язык программирования является лучшим.

Комбинация Emacs (или Vim, выбирай яд) и утилит оболочки Unix, возможно, не так проста, как современная IDE, и их, безусловно, сложнее освоить, но у них есть два < i>подавляющие преимущества по сравнению со всеми IDE, которые я когда-либо пробовал: они никогда не падают, независимо от того, насколько велика кодовая база, и они могут не отставать от моего набора текста.

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

Официальное имя или MyClass.java
<класс img ="lazyload" data-src="https://i.stack.imgur.com/ofWAB.jpg" alt="Конференц-зал или Test.java" />

Определенно интересная аналогия; это может быть даже лучше с небольшим объяснением того, как это связано напрямую. У ОП могут возникнуть трудности с подключением (хотя я прекрасно это понимаю)

@AndrewBarber Я не думаю, что аналогия действительно подходит, поскольку она не моделирует один общедоступный класс, разделяя файл с несколькими частными классами пакета. Это похоже на табличку на двери с надписью «Хизер Санти, менеджер», но на самом деле это комната с Хизер и двумя ее секретарями.

@AndrewBarber Я все равно хотел это написать; вы только что подтолкнули :) Аналогия также не может выразить самую острую озабоченность: именно из-за этой особенности компилятор должен разобрать все файлы, чтобы обнаружить все классы, где в противном случае он мог бы просто прочитать список каталогов и узнать имена всех классы верхнего уровня.

@AndrewBarber, аналогия идеально подходит под идею справочника, в длинном коридоре можно быстро найти человека, просто взглянув на дверные таблички, не нужно заходить в каждую комнату и спрашивать.

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

@Marko Java позволяет определять несколько классов в одном файле (при условии, что только один из них является общедоступным). Поскольку все классы в одном пакете должны иметь разные имена, нет другого выхода, кроме как разрешить непубличным классам иметь имя, отличное от имени файла.

Мои 2 цента: возможно, так было задумано для более быстрой локализации классов внутри пути к классам. При таком соглашении проверки имен/путей файлов достаточно для обнаружения классов.Без этого соглашения загрузчику классов пути к классам может потребоваться открыть и проанализировать файлы, чтобы найти классы

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

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

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

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

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

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

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

Читайте также: