java: (String[])List.toArray() gives ClassCastException
This is because when you use
toArray()
it returns an Object[], which can't be cast to a String[] (even tho the contents are Strings) This is because the toArray method only gets a
List
and not
List<String>
as generics are a source code only thing, and not available at runtime and so it can't determine what type of array to create.
use
toArray(new String[v2.size()]);
which allocates the right kind of array (String[] and of the right size)
ArrayList toArray method class cast exception
The class cast exception happened just because toArray() returns Object[]. Surely Object[] cannot cast to String[].
Insteadly, you can use this:
String[] list = toArray(new String[names.size()]);
which returns the right cast(String[]).
In what case does casting ArrayList Type .toArray() to (Type[]) have the potential for a Class Cast Error
It always fails.
I'm sure you're wondering why. Let's try to explain:
Unlike generics, which are entirely a figment of the compiler's imagination, an array does know its 'component' type. You can ask it:
String[] strings = new String[10];
Object[] o = strings; // compiles. This is itself problematic, see later.
System.out.println(o.getClass().getComponentType()); // prints 'java.lang.String'
o[0] = Integer.valueOf(0); // hmmmmmmmm!!!!!
String str0 = strings[0]; // ... but... wait.. that's an Integer, not a String!
Tossing the above in a java file, it....
compiles??
Yes, it does. It shouldn't have, really - the reason it compiles, even today, is that java started out allowing the above, and java does not like breaking backwards compatibility. This code used to compile, so it still does. But this is obviously not right - I have put an integer in a string array. And that's why when you run it, this does not work: You get an ArrayStoreException
on the line where you put an integer into o[0]
.
Let's try this with generics. The same thing, just, genericsed:
List<String> strings = new ArrayList<String>();
List<Object> o = strings; // the evil occurs here
// hmmm, List doesn't appear to have a getComponentType()....
o.add(Integer.valueOf(0));
String str0 = strings.get(0);
Now, sanity has been restored: That second line, where the evil occurs? The compiler doesn't let you do that. As it shouldn't, because then you run into the problems that these snippets show. In computer science-ese, array assignment is covariant, whereas with generics it is invariant. In the real world, this stuff is invariant (hence why the first snippet blows up), so generics got it right, arrays got it wrong, but we can't fix it - java should be backwards compatible.
Now that you know this, the problems with toArray() become clear:
It is not possible for the toArray() method to know what component type the list is; therefore, if you have a
List<String>
and calltoArray()
on it, the toArray code cannot possibly obtainString
from itself, unlike with arrays the component type is not stored. Generics are a figment of the compiler's imagination, it is nowhere in your class files, only in your source files. Thus, it doesn't know, so, it makes an array of objects (as in, the array that falls out oftoArray()
is technically an Object, calling itsgetComponentType
will always printclass java.lang.Object
.It is legal to assign a
String[]
toObject[]
, because the java lang spec defines arrays to be covariant. But real life isn't like that. Also, the lang spec also says that the reverse does not hold: You cannot cast an instance ofObject[]
to typeString[]
. This is why it will always fail - thetoArray()
method ALWAYS produces anObject[]
, which cannot be cast like that.But let's say you could have hypothetically done that: If you then assign a non-string object to one of the array's slots, the
ArrayStoreException
does not happen, because the component type is incorrect.And now you get a classcastexception later on when you read it back in.
Let's try it:
List<String> list = new ArrayList<String>();
list.add("Hello!");
String[] strings = (String[]) list.toArray(); // this fails...
Object[] o = strings;
o[0] = Integer.valueOf(5);
String str0 = strings[0]; // but otherwise you'd be in trouble here.
The solution
The fix is trivial:
NB: In java, we write 'operatorIndex', not 'operator_index'. When in rome, be like romans.
return operators.get(operatorIndex).operation(thisArgs.toArray(Type[]::new));
now you get no warnings, you don't need the cast, all is well. In this scenario at runtime the system does know how to make an array of Type (because you pass in a lambda that makes it). An alternative is this:
return operators.get(operatorIndex).operation(thisArgs.toArray(new Type[0]));
the provided array here (new Type[0]
) is used only to get the component type, then the array is tossed in the garbage (it's a very short lived object, so it's free garbage, fortunately), and a new one is made, but now it WILL have the proper type; it'll be a Type[]
, and not an Object[]
.
TL;DR: Do not, ever, use collections' .toArray() method. It still exists, and will continue to exist... because of the backwards compatibility thing I talked about. That's the only reason.
Collection.toArray() java.lang.ClassCastException
Change:
Class[] classes = (Class[]) map.values().toArray();
To:
Class[] classes = map.values().toArray(new Class[0]);
This gives information on which type of array to convert the Collection
to. Otherwise, it returns an array of type Object
(and that cannot be cast to an Class[]
).
Quoted from the API documentation for Collection.toArray(T[] a)
:
Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array. ...
Note thattoArray(new Object[0])
is identical in function totoArray()
.
Java, converting ArrayList to array (toArray) cannot be casted?
Try below to get the array of same type as List
List<Depot> depts = new ArrayList<Depot>();
depts.add(new Depot(1, 2));
depts.add(new Depot(1, 2));
depts.add(new Depot(1, 2));
Depot[] depots = depts.toArray(new Depot[depts.size()]);
Why there is a ClassCastException when i try to convert object[] to Student[]?
Why Student[] sList = (Student[]) pList.toArray();
wont work?
Some info from the link right below:
In Java, generic type exists at compile-time only. At runtime
information about generic type (like in your caseStudent
) is
removed and replaced withObject
type (take a look at type erasure).
That is why at runtimetoArray()
have no idea about what precise type
to use to create new array, so it uses Object as safest type, because
eachclass extends Object
so it can safely store instance of any
class.
Now the problem is that you can't cast instance of Object[] to Student[].
The JVM doesn't know (or more precisely, it is not allowed to do that. If it could do that, it would violate Java type safety) how to blindly downcast
Object[]
(the result of
toArray()) toStudent[]
. To let it know what your desired object type
is, you can pass a typed array intotoArray()
.
Solution: pList.toArray(Student[]::new)
More info: Converting 'ArrayList<String> to 'String[]' in Java
JAVA casting list of strings to string array
Use it like this - String [] myArray = myList.toArray(new String[myList.size()]);
java: (String[])List.toArray() gives ClassCastException
This is because when you use
toArray()
it returns an Object[], which can't be cast to a String[] (even tho the contents are Strings) This is because the toArray method only gets a
List
and not
List<String>
as generics are a source code only thing, and not available at runtime and so it can't determine what type of array to create.
use
toArray(new String[v2.size()]);
which allocates the right kind of array (String[] and of the right size)
Related Topics
Java Heap Terminology: Young, Old and Permanent Generations
Java.Io.Console Support in Eclipse Ide
How to Execute a Java .Class from the Command Line
Differencebetween Field, Variable, Attribute, and Property in Java Pojos
How to Set a Jvm Timezone Properly
Uninitialized Variables and Members in Java
How to Inject Dependencies into a Self-Instantiated Object in Spring
How to "Intercept" Ctrl+C in a Cli Application
How to Add Two Java.Lang.Numbers
R Error: Java.Lang.Outofmemoryerror: Java Heap Space
What's the Best Mock Framework for Java
How to Call a Stored Procedure from Java and JPA
Good Way to Encapsulate Integer.Parseint()
How to Do a Junit Assert on a Message in a Logger
How to Read the Value of a Annotation in Java
How to Write Data with Fileoutputstream Without Losing Old Data
How Are Integers Internally Represented at a Bit Level in Java