Why can you cast int[] to Object, but not to Objec

2019-07-07 08:27发布

问题:

So this works:

int i;
Object a  = (Object) i;
int[] t;
Object b = (Object) t;
String[] s;
Object[] t = (Object[]) s;

But this does not:

int[] t;
Object[] z = (Object[]) t;

All in all I get the first part (boxing), but I find it highly unintuitive that the second part does not work. Is there a specific reason why (beside String inheriting from Object and int not inheriting from Object)?

Edit:

To refine my question, this also works:

int a = 2;
int b = 3;
int c = 4;
int d = 2;
Object[] o = new Object[] {a,b,c,d};

But then the following does not:

int[] t = (int[]) o;

Surprisingly you get the same problem with String:

String sa = "a";
String sb = "b";
String sc = "c";
String sd = "d";
Object[] so = new Object[] {sa,sb,sc,sd};
String[] st = (String[]) so;

Yields a class cast exception on the last line. Still this works:

Object[] sy = (Object[])new String[]{sa,sb,sc,sd};
String[] sz = (String[]) sy;

回答1:

A int[] is an array of primitives but also an Object itself. It is not an array of Objects

There is no auto-boxing support for arrays. You need to pick the right type of array to start with and not be converting it at runtime.



回答2:

Any array, including int[] is actually an Object. This is why you can cast to Object. However, int is a primitive, so it doesn't extend Object, so you cannot cast to Object[].



回答3:

As you say: String inheriting from Object and int not inheriting from Object, that's the reason. int, boolean, double... are primitive types and they don't extend from Object. You should use Integer instead of int.

Integer[] t;
Object[] z = (Object[]) t;


回答4:

An object is a class instance or an array.

It is stated in The JLS section 4.3.1.

Now, int[] is an array, which is an Object.

String[] s; 

and

int[]

differ in following way:

Former can point to an array of String objects, but latter can point to an array of primitive int.



回答5:

I just found the answer I was looking for myself. The reason why you cannot cast int[] to Object[] is not because int is a primitive and does not extend Object, but because int[] itself does not extend Object[]. In code:

int[] t = new int[0];
Object ot = t;
System.out.println(ot instanceof Object[]);
// --> prints 'false'
String[] s = new String[0];
Object os = s;
System.out.println(os instanceof Object[]);
// --> prints 'true'

Edit: the boxing is necessary because Eclipse knows that int[] and Object[] are incompatible.

Edit II: Btw this if(obj instanceof Object[]) allows to check wether a boxed array is an array of a primitive type.



回答6:

According to Java Spec 4.10.3 Subtyping among Array Types:

  • If S and T are both reference types, then S[] >1 T[] iff S >1 T.
  • Object >1 Object[]

  • If P is a primitive type, then Object >1 P[]

S >1 T means that T is a direct subtype of S

It basically means, that int[] and Integer[] are in different branches of type hierarchy in Java and can't be cast one to another.