I have an Object
s array filled up with String
s:
Object[] array = new Object[count];
for (int i = 0; i < array.length; i++) {
array[i] = String.valueOf(i);
}
Then I refill it with Integer
s:
for (int i = 0; i < array.length; i++) {
array[i] = Integer.parseInt(array[i]);
}
I want to return an object of type Integer[]
. When I do:
return (Integer[]) array;
or
return Integer[].class.cast(array);
I get Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Integer; ([Ljava.lang.Object; and [Ljava.lang.Integer; are in module java.base of loader 'bootstrap')
.
I don't want to use streams, copying array or any other modifications or transformations. Just direct casting, maybe even via reflection.
Are there any options?
It's not an array, but you can do this with a generic list and unchecked casting using a wildcard list: List<?>
. You can even cast it when it contains objects of different types, it'll throw a ClassCastException
when you try to access them as the generic type.
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(1);
arr.add("xyz");
@SuppressWarnings("unchecked")
ArrayList<Integer> casted = (ArrayList<Integer>) (ArrayList<?>) arr;
System.out.println(casted.get(0)); // Prints 1
System.out.println(casted.get(1)); // Prints "xyz"
Integer first = casted.get(0); // Works!
// Integer second = casted.get(1); // Throws ClassCastException at runtime
// String secondStr = casted.get(1); // Doesn't compile, 'incompatible types'
String secondStrGood = (String) (Object) casted.get(1); // Works!
This is because ArrayLists just use an Object[]
array instead of a generic T[]
array, and casts on get
(sort of...)
If you try to be sneaky and retrieve the internal array backing an ArrayList through reflection, no dice there. It's just a normal Object[]
array as previously mentioned, so you get the same casting issue.
Field privateField = casted.getClass().getDeclaredField("elementData");
privateField.setAccessible(true);
// java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
Integer[] array = (Integer[]) privateField.get(casted);
If you try to be even sneakier and try this trick with a generic class instead of a List<?>
, it still doesn't work.
public class Test<T> {
public T[] array;
}
public static void main(String args[]) {
Object[] objArray = new Object[] {1, "string"};
Test<Object> test = new Test<Object>();
test.array = objArray;
@SuppressWarnings("unchecked")
Test<Integer> testInteger = (Test<Integer>) (Test<?>) test;
// java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
Integer[] intArray = testInteger.array;
}
TL;DR: best you can do is with Collection
s