Я хотел бы знать, есть ли преимущества добавления внутреннего класса над классом java в новый файл. Предполагая, что это только два способа, которыми я могу добиться этого, что необходимо. Но я хотел бы только выбрать, какой из этих двух подходов лучше.
class ABC{
LMN obj;
public static class xyz{
@customAnnotation LMN lmn;
public void set(ABC abc){
abc.obj = lmn;
}
}
}
или иметь отдельный класс вроде этого
public class xyz{
@customAnnotation LMN lmn;
public void set(ABC abc){
abc.obj = lmn;
}
}
@leonardkraemer Я считаю, что OP просил общих знаний, а не решения конкретной проблемы с кодированием, но я мог ошибаться.
«двумя способами»: вы также можете объявить несколько классов верхнего уровня в файле, при условии, что не более одного является общедоступным. Однако это не рекомендуется (просто упоминание, чтобы показать, что есть другие способы).




Единственное реальное отличие состоит в том, что статический внутренний класс будет иметь доступ к частным статическим членам и методам в родительском элементе, тогда как отдельный класс не будет.
Обычно он используется для представления внутренних объектов или для предоставления общедоступного построителя, если вы следуете шаблону построителя.
Есть несколько преимуществ, большинство из которых связано с контролем доступа:
ABC является частным пакетом, поэтому на ABC.xyz нельзя ссылаться статически вне пакета. Таким образом, вложенный класс позволяет лучше контролировать доступ (xyz может быть даже private или protected).ABC.xyz может получить доступ к частным членам ABC (статическим), что устраняет необходимость раскрывать инкапсулированные поля миру, если требуется доступ к ним из xyz.В основном это вопрос дизайн.
Из документов JAVA SE:
Why Use Nested Classes?
It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
Это означает, что если вам нужно только создать и использовать экземпляры класса xyz в контексте класса ABC, тогда имеет смысл определить его как внутренний класс внутри ABC.
Это скрывает внутренний класс от внешнего мира и дает внешнему классу доступ к его закрытым членам данных (вообще говоря, подробнее см. Ниже). Это упрощает чтение и понимание вашего кода, но, что более важно, увеличивает инкапсуляцию и сокрытие данных, гарантируя, что класс будет виден и доступен только тем, кому он нужен. Это фундаментальный принцип объектно-ориентированного программирования.
На более практическом примечании:
В Java есть два разных типа вложенных классов: статические и нестатические. Каждый тип определяет разные отношения прав доступа со своим определяющим внешним классом. Вы можете прочитать больше об отличиях здесь.
Пример действительно приводит к преимуществу наличия нестатического внутреннего класса:
class ABC {
LMN obj;
List<Xyz> xyzs = new ArrayList<>();
public class Xyz {
@customAnnotation LMN lmn;
public void foo(){
ABC.this.obj = lmn;
}
}
... new Xyz(); // Passes the this of ABC.
}
Можно сделать конструктор Xyz закрытым, чтобы разрешить только ABC правильное создание Xyzs.
А именно, что когда-либо Xyz знает ABC, которая его создала: ABC.this. Полезно для контейнеров.
Для статических внутренних классов это может быть локальное использование внутри самого класса или класс параметра / результата / исключения для метода в ABC, связанный с использованием класса ABC.
Такой класс полезен, поскольку API не изменится, если параметр метода - просто Xyz, но Xyz получит и дополнительное поле. Если бы у метода появилось дополнительное поле, нужно было бы обновить все его использования. Для библиотеки, которая может затруднить обратную совместимость (новый метод).
Для лямбда-выражений с классическим forEach или для циклов такой статический класс тоже может быть полезен.
Наконец, enum, определяющие диапазон значений домена, часто также являются локальными по отношению к классу.
В стандартной java есть случай Character с обширной поддержкой Unicode в виде внутренних классов Character.SubSet, UnicodeBlock, UnicodeScript.
«Если предположить, что это только два пути, которые я могу достичь, это необходимо». Почему бы вам тогда не задать вопрос, который на самом деле является вашей проблемой? Может быть, лучшее решение будет совершенно другим. Классическая проблема xy