В Java можно определить несколько высокоуровневых классов в единственном файле, если это самое большее один из них общедоступен (см. JLS §7.6). Посмотрите ниже, например.
Есть ли опрятное название этой техники (аналогичный inner
, nested
, anonymous
)?
JLS говорит, что система может осуществить ограничение, которым не могут быть эти вторичные классы referred to by code in other compilation units of the package
, например, их нельзя рассматривать как частных на пакет. Это - действительно что-то, что изменяется между реализациями Java?
например, PublicClass.java:
package com.example.multiple;
public class PublicClass {
PrivateImpl impl = new PrivateImpl();
}
class PrivateImpl {
int implementationData;
}
Мое предложенное имя для этого метода (включая несколько классов верхнего уровня в одном исходном файле) было бы "беспорядок". Серьезно, я не думаю, что это хорошая идея - вместо этого я бы использовал вложенный тип в этой ситуации. Тогда все еще легко предсказать, в каком исходном файле он находится. Я не верю, что есть официальный термин для этого подхода.
Что касается того, действительно ли это меняется между реализациями - я очень сомневаюсь в этом, но если вы в первую очередь избегаете этого, вам никогда не придется беспокоиться :)
1. Есть ли у этой техники аккуратное название (аналогичное внутреннему, вложенному, анонимному)?
Мультиклассовая однофайловая демонстрация.
2. В JLS говорится, что система может применять ограничение, согласно которому на эти вторичные классы нельзя ссылаться с помощью кода в других единицах компиляции пакета, например, они не могут рассматриваться как частные для пакета. Это действительно что-то, что меняется между реализациями Java?
Я не знаю ни одной, которая не имеет этого ограничения - все компиляторы на основе файлов не позволят вам ссылаться на классы исходного кода в файлах, которые не имеют имени то же, что и название класса. (если вы скомпилируете файл с несколькими классами и поместите классы в путь к классам, то любой компилятор найдет их)
javac активно не запрещает это, но у него есть ограничение, которое в значительной степени означает, что вы никогда не захотите ссылаться на класс верхнего уровня из другого файла, если его имя не совпадает с именем файла, в котором он находится.
Предположим, у вас есть два файла, Foo.java и Bar.java.
Foo.java содержит:
Bar.java содержит:
Предположим также, что все классы находятся в одном пакете ( и файлы находятся в одном каталоге).
Что произойдет, если Foo.java ссылается на Baz, но не на Bar, и мы попытаемся скомпилировать Foo.java? Компиляция завершается неудачно с такой ошибкой:
Foo.java:2: cannot find symbol
symbol : class Baz
location: class Foo
private Baz baz;
^
1 error
Это имеет смысл, если задуматься. Если Foo.java ссылается на Baz, но нет Baz.java (или Baz.class), как javac может узнать, в каком исходном файле искать?
Если вместо этого вы укажете javac скомпилировать Foo.java и Bar.java в то же время или даже если вы ранее скомпилировали Bar.java (оставив Baz.class, где javac может его найти), тогда эта ошибка исчезнет. Однако из-за этого процесс сборки выглядит очень ненадежным и нестабильным.
Поскольку фактическое ограничение, которое больше похоже на «не относитесь к классу верхнего уровня из другого файла, если он не имеет того же имени, что и файл, в котором он находится, или вы также ссылаетесь на класс, который находится в том же самом файле». "файл, названный так же, как и файл", трудно понять, люди обычно придерживаются гораздо более простого (хотя и более строгого) соглашения, заключающегося в том, что просто помещают один класс верхнего уровня в каждый файл. Это также будет лучше, если вы когда-нибудь передумаете, должен ли класс быть публичным или нет.
Иногда действительно есть веская причина, почему каждый делает что-то определенным образом.
Я полагаю, вы просто вызываете PrivateImpl
, что это такое: закрытый класс верхнего уровня
. Вы также можете объявить непубличные интерфейсы верхнего уровня
.
например, в другом месте на SO: Непубличный класс верхнего уровня против статического вложенного класса
Что касается изменений в поведении между версиями, было обсуждение того, что «отлично работает» в 1.2 .2. но перестал работать в 1.4 на форуме Sun: Компилятор Java - невозможно объявить закрытые классы верхнего уровня в файле .