Поскольку объемлющий класс может получить доступ к закрытым полям своего внутреннего класса, когда они должны быть объявлены закрытыми, по умолчанию или общедоступными для частного внутреннего класса?
Java - частный член против члена по умолчанию частного внутреннего класса
Ответы (3)
На первый взгляд кажется неуместным указывать модификатор доступа для членов внутренних классов. Как вы указали, содержащий класс в любом случае может получить доступ ко всем членам.
Однако есть несколько дополнительных соображений:
- Иногда внутренние классы объявляются
public
и служат частью определения интерфейса содержащего класса. Возможно, у внешнего класса есть метод, возвращающий экземпляр внутреннего класса. В этом случае на внутренний класс распространяются те же рекомендации по видимости членов, что и на классы верхнего уровня. В этом случае предпочтительнее сохранить детали реализацииprivate
. - Хотя компилятор не навязывает это, пометка членов внутреннего класса как
private
может задокументировать для будущих сопровождающих, что эти члены не предназначены для прямого доступа из кода внешнего класса. Конечно, в этот момент может потребоваться рефакторинг внутреннего класса в его собственный класс верхнего уровня. - Иногда внутренние классы используются в сочетании с фреймворками на основе отражения, которые работают только с
public
элементами. Например, сериализатор JSON Jackson по умолчанию работает только сpublic
участниками. Можно заставить его работать с членамиprivate
, выполнив несколько действий, таких как добавление геттераpublic
. Это дополнительная работа, поэтому может быть удобнее сначала объявить элементpublic
. - Если вышеуказанные пункты неприменимы и при отсутствии каких-либо других требований, самый простой и короткий код — полностью исключить модификатор доступа (default/package-private). Это будет вопрос стиля кодирования для проекта.
Это хороший стиль объявлять все приватным, если только нет причин использовать приватный или общедоступный пакет. И эта причина не должна быть так удобнее.
Все, что не является частным, может использоваться вне вашего класса, и, таким образом, изменения в любом нечастном аспекте вашего кода могут нарушить работу других мест кода или даже внешнего кода, который зависит от вашего кода. Усложняет, а иногда даже делает невозможным рефакторинг и изменение внутренней работы ваших классов.
В частном случае внутреннего класса private все видно только содержащему его классу. То есть видимость членов внутренних классов значения не имеет. С другой стороны, если вы работаете над библиотекой, обычной практикой является предоставление интерфейсов только как контракт. Сохранение деталей реализации полностью скрытыми.
Не только внешний класс, но и другие классы могут получить доступ к внутреннему классу и его членам. Поэтому, если вы хотите сделать члены внутреннего класса доступными только для его внешнего класса, вы можете объявить их как частные. рассмотрим следующий пример
В одном пакете com.exercise.test
есть 2 класса, а в нем есть классы OtherClass
и SampleClassWithInner
, которые содержат внутренний класс InnerClass
.
члены InnerClass
, объявленные как частные, недоступны в OtherClass
. Где как это доступно в SampleClassWithInner
обратитесь к этому коду для большей ясности
package com.exercise.test;
//import com.exercise.test.SampleClassWithInner.InnerClass;
public class OtherClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
SampleClassWithInner sampleobj = new SampleClassWithInner();
SampleClassWithInner.InnerClass innerobj = sampleobj.new InnerClass();
// innerobj.var1=5; //compile time error
innerobj.setVar1(5); // ok works
// System.out.println("value of inner variable declared in other
// class"+innerobj.var1);// compile time error
System.out.println("value of inner variable declared in other class "
+ innerobj.getVar1());
sampleobj.innerMethodDemo();
}
}
а также
package com.exercise.test;
public class SampleClassWithInner {
class InnerClass {
private int var1;
private int var2;
public int getVar1() {
return var1;
}
public void setVar1(int var1) {
this.var1 = var1;
}
public int getVar2() {
return var2;
}
public void setVar2(int var2) {
this.var2 = var2;
}
}
public void innerMethodDemo() {
InnerClass obj = new InnerClass();
obj.var1 = 10;
System.out.println("this is form the method in outer class " +
obj.var1);
}
}