Why are array assignments incompatible, even thoug

2020-04-10 10:07发布

问题:

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

the above code will give no error/warnings. But why is the same not applicable for the below mentioned code?

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

my question is, since int can hold any and all byte values, why is this not the case with arrays?

they are both holding the addresses afterall. And this would be upcasting if this was possible for ref variables.

回答1:

The language spec defines subtyping between array types in 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[]

The final bullets ("If P is a primitive type...") show that the language does not define any relationship between arrays of differing primitive types. The only valid assignments are:

byte[] bs = new byte[10];

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

This doesn't provide an answer as to why it is like this; you'd have to ask the language designers. However, simple examples like that shown by Eran demonstrate why it would not be safe to do as OP proposes.

It should be noted that the first line - which permits an assignment like

Object[] obj = new String[10];
obj[0] = new Object();  // ArrayStoreException!

was a design error: that arrays are covariant makes them not type safe. This is one reason to strongly prefer generics to arrays, since generics are invariant, and so prevent such assignments.



回答2:

The array created by new byte[10] can contain 10 byte values. If you were able to assign it to a variable of type int[], the compiler would assume (mistakenly) that your array of bytes can contain 10 int values.

Consider the following code, which is invalid:

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

and the following code, which is valid:

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

If int[] i2 = new byte[10]; was valid, the compiler would have allowed you to store an int in a variable of type byte.