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

时间:2018-06-07 06:47:50

标签: java pointers casting pass-by-reference

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

上面的代码不会给出任何错误/警告。但为什么同样不适用于下面提到的代码?

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可以保存任何和所有字节值,为什么数组不是这种情况呢?

他们都在拿着地址。如果这对于ref变量是可能的话,这将是 upcasting

2 个答案:

答案 0 :(得分:8)

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类型的变量中。

答案 1 :(得分:5)

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

  

以下规则定义了数组之间的直接超类型关系   类型:

     
      
  • 如果ST都是参考类型,那么S[] >1 T[] iff S >1 T

  •   
  • Object >1 Object[]

  •   
  • Cloneable >1 Object[]

  •   
  • java.io.Serializable >1 Object[]

  •   
  • 如果P是基本类型,则:

         
        
    • Object >1 P[]

    •   
    • Cloneable >1 P[]

    •   
    • java.io.Serializable >1 P[]

    •   
  •   

最终的项目符号(“如果P是基本类型......”)表明该语言没有定义不同基元类型的数组之间的任何关系。唯一有效的作业是:

byte[] bs = new byte[10];

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

这并没有提供为什么这样的答案;你必须问语言设计师。然而,像Eran所示的简单示例证明了为什么OP提出的做法不安全。

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

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

是一个设计错误:数组是协变的,因此它们不是类型安全的。这是强烈偏好泛型到数组的一个原因,因为泛型是不变的,因此阻止了这样的赋值。