[英]length of array of private class is not accessible
Please consider the following code : 请考虑以下代码:
class A {
B[] arr = new B[10];
private class B {}
}
class C {
void fun(){
A a = new A();
Object arr = a.arr;
Object len = a.arr.length; // !! ERROR
}
}
As I written in code. 正如我在代码中写的那样。 a.arr.length;
is giving error. 给出错误。
I actually understand why it is happening. 我真的明白为什么会这样。 It is because sub class B
is private. 这是因为子类B
是私有的。 But still why it is happening. 但仍然为什么会这样。 In class A, property arr
was accessible, but why not it's length. 在A类中,属性arr
是可访问的,但为什么不是它的长度。 Is there any explanation for this in jls or anywhere. 在jls或任何地方有没有任何解释。
I just want a clear explanation for this behaviour. 我只想对这种行为做出明确的解释。 I know private things cannot be accessed outside of its class. 我知道私人事物不能在同类之外访问。 But a public array could be. 但公共阵列可能是。 No matter of what type it is. 无论是什么类型。 And if anything is accessible outside, then its public properties should also be accessed. 如果外面有任何东西可以访问,那么也应该访问它的公共属性。 But here it is not happening. 但这里没有发生。
Edit : I found that in C# it is not even possible to create an array of private class. 编辑:我发现在C#中甚至不可能创建一个私有类数组。 In java if we cannot access anything, and cannot even know the length of the array of private class then what is the use of creating an array of private class. 在java中如果我们无法访问任何东西,甚至无法知道私有类数组的长度那么创建私有类数组有什么用。
The reason for this is a combination of two statements in the JLS: 原因是JLS中两个语句的组合:
Item 6.6.1 Determining accessibility: 项目6.6.1确定可访问性:
An array type is accessible if and only if its element type is accessible. 当且仅当其元素类型可访问时,才能访问数组类型。
This means that if T
is private, T[]
is also considered private. 这意味着如果T
是私有的, T[]
也被认为是私有的。
Item 10.7 Array members: 项目10.7阵列成员:
The
public final
fieldlength
, which contains the number of components of the array.public final
字段length
,包含数组的组件数。 length may be positive or zero. 长度可以是正数或零。
Remember that accessibility is determined at compile-time based on the type of reference you have, not on the type of the actual object! 请记住,可访问性是在编译时根据您具有的引用类型而不是实际对象的类型确定的!
Now, let's go into a little more elaborate example to demonstrate what this means. 现在,让我们进入一个更详细的例子来证明这意味着什么。 I added a toString()
and a constructor to B
. 我向B
添加了一个toString()
和一个构造函数。
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 + ")";
}
}
}
Now, in class C, we use: 现在,在C类中,我们使用:
A a = new A();
Object plain = a.plain;
String s = plain.toString();
This is legal, because a.plain
is a visible field. 这是合法的,因为a.plain
是一个可见字段。 s
will contain Hidden class B(99)
. s
将包含Hidden class B(99)
。 But if you try: 但如果你尝试:
String s = a.plain.toString(); // Compile error
This will not be allowed, because althogh toString()
in B
is public, B
itself is private, you have no access to its members, whether public or private. 这是不允许的,因为B
althogh toString()
是公共的, B
本身是私有的,你无法访问其成员,无论是公共还是私有。
Note that we cannot access i
in B
despite its being public. 请注意,尽管B
公开,但我们无法访问B
i
。 If we use: 如果我们使用:
plain.i
Then since i
is not a member of Object
, you get a compile error. 然后因为i
不是Object
的成员,所以会出现编译错误。 And if we use: 如果我们使用:
a.plain.i
Then since a.plain
is private, you can't access its members, as we already tried. 然后,由于a.plain
是私有的,因此我们已经尝试过,您无法访问其成员。
So now we go and look at the issue of arrays. 所以现在我们来看看数组的问题。 Suppose we write: 假设我们写道:
Object[] objArr = a.arr;
int len = objArr.length;
This is legal, despite the fact that objArr
is internally AB[]
. 尽管objArr
是内部AB[]
, objArr
是合法的。 We have a reference to Object[]
, Object
is public and so is Object[]
. 我们引用了Object[]
, Object
是public,因此是Object[]
。 But: 但:
int len = a.arr.length;
Gives you a compile error exactly as we got for a.plain.toString()
. 完全按照我们为a.plain.toString()
获得的编译错误。 Although length
is public in itself, you are accessing it through a reference to AB[]
. 尽管length
本身是公共的,但您通过引用AB[]
来访问它。 AB[]
is not accessible because AB
is not accessible. AB[]
无法访问,因为AB
无法访问。 And therefore, because length
is its member, you cannot access it. 因此,因为length
是其成员,所以您无法访问它。 You simply cannot access any member of a reference type that is not visible to you, by the first rule above. 您无法通过上面的第一条规则访问您不可见的任何引用类型的成员。
It is interesting to note that the following is legal: 有趣的是,以下是合法的:
Object firstItem = a.arr[0];
We can use the expression a.arr[0]
because it is not considered an attempt to access a member of the array. 我们可以使用表达式a.arr[0]
因为它不被视为访问数组成员的尝试。 The elements of the array are not considered to be members in it. 数组的元素不被视为其中的成员。 a.arr[0]
is simply an expression on an array reference that resolves to type AB
. a.arr[0]
只是解析为AB
类型的数组引用的表达式。 There is no problem with such an expression as long as we don't try to access members of the item. 只要我们不尝试访问项目的成员,这样的表达就没有问题。
firstItem.toString() // Good
a.arr[0].toString() // Bad
Summary 摘要
length
of an array. 这包括数组的length
。 length
is available in Object []
so you can get it through that. length
在Object []
可用,因此您可以通过它。 Do this: 做这个:
class A {
B[] arr = new B[10];
public int getArrayLength()
{
return arr.length;
}
private class B {}
}
class C {
void fun(){
A a = new A();
Object arr = a.arr;
//Object isn't type safe
//Object len = a.getArrayLength();
int len = a.getArrayLength();
}
}
According to JavaDocs 根据JavaDocs
At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. 在成员级别,您也可以使用public修饰符或no修饰符(package-private),就像使用顶级类一样,并且具有相同的含义。 For members, there are two additional access modifiers: private and protected. 对于成员,还有两个额外的访问修饰符:private和protected。 The private modifier specifies that the member can only be accessed in its own class. private修饰符指定只能在自己的类中访问该成员。 The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package. protected修饰符指定只能在其自己的包中访问该成员(与package-private一样),此外,还可以在另一个包中通过其类的子类访问该成员。
Knows that the question is about accessing the length
field. 知道问题是关于访问length
字段。 But, it was interesting for me to find that the length
can be determined by enhanced-for-loop, not by making changes to access privileges or using reflection: 但是,有趣的是我发现length
可以通过增强循环来确定,而不是通过更改访问权限或使用反射来确定:
int length = 0;
for(Object o : a.arr) {
length++;
}
Few interesting statements about arrays were: 关于数组的几个有趣的陈述是:
In the Java programming language, arrays are objects (§4.3.1), are dynamically created, and may be assigned to variables of type Object (§4.3.2). 在Java编程语言中,数组是对象(§4.3.1),是动态创建的,可以分配给Object类型的变量(§4.3.2)。 All methods of class Object may be invoked on an array. 可以在数组上调用Object类的所有方法。
An array's length is not part of its type. 数组的长度不是其类型的一部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.