Reputation: 1095
No error
Object[] a = new String[]{"12","34","56"};
String[] b = (String[]) a;
No error
Object a = new String[]{"12","34","56"};
String[] b = (String[]) a;
Run time error : ClassCastException
Object[] a = new Object[3];
a[0] = "12";
a[1] = "34";
a[2] = "56";
String[] b = (String[]) a;
Run time error : ClassCastException
Object[] a = {"12","34","56"};
String[] b = (String[]) a;
Of course, we can downcast an Object[]
variable back to String[]
if it was created as an String[]
.
My question is why we can not cast Object[]
to String[]
when it was created as Object[]
but all its members are String? Is it because of security reason or just not that useful to implement this?
Upvotes: 11
Views: 21299
Reputation: 3051
This post provides a way to quickly create a String[]
out of an Object[]
.
arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
Assuming of course that imageUrls
is not null
.
Upvotes: 0
Reputation: 328598
It is defined in the JLS #5.5.3. In substance, a cast:
r = new RC[]; TC[] t = (TC[]) r;
"works" at runtime iif RC is a subtype of TC (or TC itself). Whether RC actually only contains TCs is irrelevant and the compile-time type of r is not used either (what matters is the runtime type):
r = new String[]; Object[] t = (Object[]) r;
, butr = new Object[]; String[] t = (String[]) r;
.JLS extract:
If T is an array type TC[], that is, an array of components of type TC, then a run-time exception is thrown unless one of the following is true:
- TC and RC are the same primitive type.
- TC and RC are reference types and type RC can be cast to TC by a recursive application of these run-time rules for casting.
In your examples 3 and 4, RC = Object and TC = String and Object is not a subtype of String. In your examples 1 and 2, RC = String and TC = String so it works.
Note: the type in this context is the runtime type.
Upvotes: 5
Reputation: 2456
Here's two reasons I can think of.
Firstly, if you change the original array, the casted array can become invalid. e.g.
Object[] a = {"12","34","56"};
String[] b = (String[]) a; // pretend this is legal. a and b now point to the same array
a[0] = new Object(); // clearly ok
String x = b[0]; // No longer a string! Bad things will happen!
Secondly, the example you have chosen is very simple, but if you have a very large Object[]
array and it's not clear to the compiler what is filling it, then it has no way of validating that every element of the array satisfies the cast.
Object[] a = new Object[10000];
// lots of weird and whacky code to fill the array with strings
String[] b= (String[]) a; // valid or no? The best-defined answer is to say no.
Upvotes: 8
Reputation: 41945
Because you are not casting individual member of array, you are casting the whole array instance which is of type Object[]
and not String[]
.
Object[] a = new String[]{"12","34","56"};
Here the instance is of type String[]
and the compile time type is Object[]
.
And in the next line you are casting it back to String[]
which is allowed as the actual type or runtime type is String[]
.
But Object[] a = new Object[3];
here the actual type and Compile time type is Object[]
and it is not String[]
. So an Object[]
cannot be String[]
.
Object[] a = new Object[1];
a[0] = "a"; //Actual type String
So you can do this:
String aStr = (String)a[0];
Upvotes: 4
Reputation: 136002
If all members Object array were Strings at the moment of casting you still could assign objects that are not Strings to the elements of this array later. So you would have String array with elements which are not Strings.
Upvotes: 2
Reputation: 111239
Array objects are not just a collection of their elements, they have classes just like other objects. The class for array of strings is a subclass of array of objects. That's why there's no error in your 1 or 2, but the last two are equivalent to
Object o = new Object();
String s = (String) o;
Upvotes: 2