为什么数组赋值不兼容,即使它们的数据类型是兼容的?
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!
是一个设计错误:数组是协变的,这使得它们类型不安全。这是强烈偏好泛型而不是数组的原因之一,因为泛型是 不变的 ,因此可以防止此类赋值。
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
andT
are both reference types, thenS[] >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;
这并没有提供关于为什么是这样的答案;你得问语言设计师。然而,像
应该注意的是,第一行允许像
这样的赋值Object[] obj = new String[10];
obj[0] = new Object(); // ArrayStoreException!
是一个设计错误:数组是协变的,这使得它们类型不安全。这是强烈偏好泛型而不是数组的原因之一,因为泛型是 不变的 ,因此可以防止此类赋值。