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?
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.
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.
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];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With