Причиной этого является сочетание двух утверждений в JLS:
Item 6.6.1 Определение доступности:
Тип массива является доступным, если и только если его тип элемента доступны.
Это означает, что если T
является закрытым, T[]
также считается приватным.
Item 10.7 элементов массива:
public final
поле length
, который содержит число компонентов массива. длина может быть положительной или нулевой.
Помните, что доступность определяется во время компиляции на основе типа ссылки у вас есть, а не от типа фактического объекта!
Теперь давайте рассмотрим более подробный пример, чтобы продемонстрировать, что это значит. Я добавил toString()
и конструктор в B
.
class A {
B[] arr = { new B(1), new B(2), new B(3), new B(4) };
B plain = new B(99);
private class B {
public int i;
B(int i) {
this.i = i;
}
@Override
public String toString() {
return "Hidden class B(" + i + ")";
}
}
}
Теперь, в классе С, мы используем:
A a = new A();
Object plain = a.plain;
String s = plain.toString();
Это является законным, поскольку a.plain
является видимым полем. s
будет содержать Hidden class B(99)
. Но если вы попробуете:
String s = a.plain.toString(); // Compile error
Это не будет разрешено, потому что Althogh toString()
в B
является публичным, B
сама является частным, не имеют доступа к своим членам, будь то государственные или частные.
Отметим, что мы не можем получить доступ к i
в B
, несмотря на то, что он является публичным. Если мы используем:
plain.i
Тогда так i
не является членом Object
, вы получите ошибку компиляции. И если мы будем использовать:
a.plain.i
Тогда так a.plain
является частным, вы не можете получить доступ к своим членам, как мы уже пробовали.
Итак, теперь мы рассмотрим вопрос о массивах. Предположим, мы пишем:
Object[] objArr = a.arr;
int len = objArr.length;
Это является законным, несмотря на то, что objArr
является внутренне A.B[]
. У нас есть ссылка на Object[]
, Object
является общедоступным, и поэтому Object[]
. Но:
int len = a.arr.length;
Дает ошибку компиляции точно так, как мы получили для a.plain.toString()
. Хотя length
является общедоступным, вы получаете доступ к нему через ссылку на A.B[]
. A.B[]
недоступен, так как A.B
недоступен. И поэтому, поскольку length
является его членом, у вас нет доступа к нему. Вы просто не можете получить доступ к любому члену ссылочного типа, который не отображается вам, по первому правилу выше.
Интересно отметить, что следующий является правовым:
Object firstItem = a.arr[0];
Мы можем использовать выражение a.arr[0]
, потому что это не считается попыткой доступа к элементу массива. Элементы массива не считаются членами в нем. a.arr[0]
- это просто выражение на ссылке массива, которая разрешает вводить A.B
. Нет никаких проблем с таким выражением, пока мы не пытаемся получить доступ к элементам элемента.
Резюме
- Это нормально, чтобы держать на обращение частного типа, если вы бросили его в какой-то общественный надтип.
- Это нормально, чтобы получить конкретный элемент в массиве частного типа. Индексирование массива не считается «доступом к члену», это просто выражение в ссылке, которое дает ссылку на его тип члена. Что вам нужно будет сделать для чего-то публичного для использования.
- Нельзя попробовать получить доступ к члену с заданной ссылкой на закрытый тип, даже если член является общедоступным. Это включает в себя
length
массива.
- Это нормально, чтобы получить доступ к этому публичному пользователю с помощью приведения в супертип, если он доступен в этом супертипе.
length
можно приобрести в Object []
, чтобы вы могли это получить.
- Доступ к публичному члену частного типа, который не существует в доступном супертипе, недоступен.
Личные данные могут быть доступны только через общедоступный метод того же класса. 'arr', поэтому он отображается внутри' A', но 'B' является закрытым, поэтому нет. удалить private из 'B', он не будет показывать никаких ошибок. – Rustam
Любопытно, что вы действительно можете использовать выражение 'a.arr [0]'. – RealSkeptic
Что касается вашего редактирования, существует множество применений для массива частного класса. Вы можете использовать его для внутренних целей охватывающего класса. Или вы можете отображать в нем элементы как возвращаемые значения и т. Д. – RealSkeptic