为什么数组赋值不兼容,即使它们的数据类型是兼容的?

Why are array assignments incompatible, even though their data types are?

byte b =10;   
int a = b;   // Primitive data type widening
             // Works perfectly fine

上面的代码不会给出error/warnings。但为什么同样不适用于下面提到的代码?

byte[] b = new byte[10];
int[] i1 = b;             //Cannot convert from byte[] to int[]
int[] i2 = new byte[10];  //Cannot convert from byte[] to int[]

我的问题是,既然 int 可以保存任何和所有字节值,为什么数组不是这种情况?

毕竟他们都持有地址。这将是 upcasting 如果这对于 ref 变量是可能的。

new byte[10] 创建的数组可以包含 10 个 byte 值。如果您能够将其分配给 int[] 类型的变量,编译器会(错误地)假设您的 byte 数组可以包含 10 个 int 值。

考虑以下无效代码:

byte[] b = new byte[10];
b[0] = 10000; // too large for byte

和下面的有效代码:

int[] i2 = new int[10];
i2[0] = 10000;

如果 int[] i2 = new byte[10]; 有效,编译器将允许您将 int 存储在 byte.

类型的变量中

语言规范定义了 Sec 4.10.3 中数组类型之间的子类型:

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[]

  • If P is a primitive type, then:

    • Object >1 P[]

    • Cloneable >1 P[]

    • java.io.Serializable >1 P[]

最后的项目符号 ("If P is a primitive type...") 表明该语言没有定义不同原始类型数组之间的任何关系。唯一有效的分配是:

byte[] bs = new byte[10];

byte[] bs2 = bs;
Object obj = bs;
Cloneable cl = bs;
Serializable ser = bs;

这并没有提供关于为什么是这样的答案;你得问语言设计师。然而,像 所示的简单示例说明了为什么按照 OP 建议的那样做是不安全的。

应该注意的是,第一行允许像

这样的赋值
Object[] obj = new String[10];
obj[0] = new Object();  // ArrayStoreException!

是一个设计错误:数组是协变的,这使得它们类型不安全。这是强烈偏好泛型而不是数组的原因之一,因为泛型是 不变的 ,因此可以防止此类赋值。