在 Java 中铸造数组过程? (协方差和 [LObject)

Casting array process in Java? (covariance and [LObject)

我的问题是 Java 中的铸造过程究竟如何? 假设我们有

User[] users = new User[2];//<-- here we get at runtime [LUser class
Object[] objects = (Object[]) users;//<-- here we get at runtime [LObject class

public class [LUser extends Object implements Serializable, Cloneable{

}

public class [LObject extends Object implements Serializable, Cloneable{

}

我知道由于 User 是 Object 的数组协变性,User[] 也是 Object[]。但是关于 class 创建([LUser 和 [LObject 问题)的解释破坏了我对协方差的理解。因为如果我们注意到 [LUser 和 [LObject

User[] users = new User[2];
Object[] objects = (Object[]) users;
//<-- here we cast [LUser to [LObject but [LUser doesn't extends [Lobject

那么铸造过程究竟如何呢? 可能问题看起来很疯狂,但从逻辑上讲我得到了这个结果。在最坏的情况下,我可以认为在语法上 Java 将 User[] 转换为 Object[] 但那时为什么我们需要像 [LObject, [LUser

这样的对象创建

根据JLS 4.10.3. Subtyping among Array Types (link ):

The following rules define the direct supertype relation among array types:

  • If S and T are both reference types, then S[] >1 T[] iff S >1 T.

  • Object >1 Object[]

  • Cloneable >1 Object[]

  • java.io.Serializable >1 Object[]

以上意思如下。当然你不能这么写,但那是 Java 数组子类型化规则的等价物。

//                     Rule #2           Rule #3    Rule #4
class Object[] extends Object implements Cloneable, Serializable {
}

//                   Rule #1
class User[] extends Object[] {
}

更新

另外,JLS 10.7. Array Members说:

The members of an array type are all of the following:

  • The public final field length, which contains the number of components of the array. length may be positive or zero.

  • The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].

    A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.

  • All the members inherited from class Object; the only method of Object that is not inherited is its clone method.

那就意味着:

class Object[] extends Object implements Cloneable, Serializable {
    public final int length = /*value from array creation*/;
    public Object[] clone() {
        try {
            return (Object[]) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
    }
}

class User[] extends Object[] {
    public User[] clone() {
        return (User[]) super.clone();
    }
}