【问题标题】:Why are array assignments incompatible, even though their data types are?为什么数组赋值不兼容,即使它们的数据类型是不兼容的?
【发布时间】:2018-06-07 06:47:49
【问题描述】:
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 变量可以这样做,这将是向上转型

【问题讨论】:

  • int[] i1 = b; - b 没有复制到i1i1 将指向b 指向的相同地址。那么,如果将整数分配给 i1[0](引用 b 并且是字节数组 - 不是 int 数组)会发生什么?
  • 对不起,我没有关注,您能详细说明一下吗? @BackSlash

标签: java pointers casting pass-by-reference


【解决方案1】:

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

【讨论】:

  • 很好的例子,但它可能会提示人们为什么它适用于引用类型的数组(例如Object[] objs = new String[10];)。
  • 跟进同样的解释,为什么 Wrapper Classes 中同样的解释不起作用? Byte b = new Byte[10]; Integer i = b; 它们是兼容的,Byte IS A RELATION 与 Integer,不应该动态调度允许这样做,只需首先检查 Byte 类中的参数和然后将其存储到 Integer 类 ref 变量中?
  • @AshishSharma 你的意思是问为什么Byte[] byteArr = new Byte[10]; Integer[] integerArr = byteArr; 不起作用?
  • @AshishSharma 为什么将字节数组分配给整数变量?数组不是 Integer 的子类。并且将 Byte 数组分配给 Byte 变量也没有任何意义。这就是为什么我认为你的评论中有错字。
  • "Byte IS A RELATION with Integer" ByteInteger 之间没有这种关系。 byteint 之间甚至没有关系;只是语言定义了从byteint 的转换(扩大转换)。
【解决方案2】:

语言规范在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!

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

【讨论】:

  • 虽然Eran的回答很好理解,但这个回答是正确的。
猜你喜欢
  • 1970-01-01
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 2013-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多