casting Object array to Integer array error - java

What's wrong with the following code?
Object[] a = new Object[1];
Integer b=1;
a[0]=b;
Integer[] c = (Integer[]) a;
The code has the following error at the last line :
Exception in thread "main" java.lang.ClassCastException:
[Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;

Ross, you can use Arrays.copyof() or Arrays.copyOfRange() too.
Integer[] integerArray = Arrays.copyOf(a, a.length, Integer[].class);
Integer[] integerArray = Arrays.copyOfRange(a, 0, a.length, Integer[].class);
Here the reason to hitting an ClassCastException is you can't treat an array of Integer as an array of Object. Integer[] is a subtype of Object[] but Object[] is not a Integer[].
And the following also will not give an ClassCastException.
Object[] a = new Integer[1];
Integer b=1;
a[0]=b;
Integer[] c = (Integer[]) a;

You can't cast an Object array to an Integer array. You have to loop through all elements of a and cast each one individually.
Object[] a = new Object[1];
Integer b=1;
a[0]=b;
Integer[] c = new Integer[a.length];
for(int i = 0; i < a.length; i++)
{
c[i] = (Integer) a[i];
}
Edit: I believe the rationale behind this restriction is that when casting, the JVM wants to ensure type-safety at runtime. Since an array of Objects can be anything besides Integers, the JVM would have to do what the above code is doing anyway (look at each element individually). The language designers decided they didn't want the JVM to do that (I'm not sure why, but I'm sure it's a good reason).
However, you can cast a subtype array to a supertype array (e.g. Integer[] to Object[])!

Or do the following:
...
Integer[] integerArray = new Integer[integerList.size()];
integerList.toArray(integerArray);
return integerArray;
}

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
you try to cast an Array of Object to cast into Array of Integer. You cant do it. This type of downcast is not permitted.
You can make an array of Integer, and after that copy every value of the first array into second array.

When casting is done in Java, Java compiler as well as Java run-time check whether the casting is possible or not and throws errors in case not.
When casting of Object types is involved, the instanceof test should pass in order for the assignment to go through.
In your example it results
Object[] a = new Object[1];
boolean isIntegerArr = a instanceof Integer[]
If you do a sysout of the above line, it would return false;
So trying an instance of check before casting would help.
So, to fix the error, you can either add 'instanceof' check
OR
use following line of code:
(Arrays.asList(a)).toArray(c);
Please do note that the above code would fail, if the Object array contains any entry that is other than Integer.

Related

Can't cast array of Object to array of generic type when generic type implements interface

I'm implementing a Quicksort class in Java. For sorting to work, the items that are to be sorted need to be comparable, for example by implementing the Comparable interface. However, implementing Comparable gives me problems when casting at runtime in a method that returns array slices:
public class QuickSorter<T extends Comparable<T>> {
...
private T[] sliceOfArray(T[] arr, int start, int end) {
Object[] slice = new Object[end - start];
for (int i = start; i < end; i++) {
slice[i] = arr[i];
}
return (T[]) slice; // Throws exception at runtime.
}
}
The exception is:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
at com.sortingalgos.QuickSorter.sliceOfArray(QuickSorter.java:55)
at com.sortingalgos.QuickSorter.sort(QuickSorter.java:11)
at com.sortingalgos.MainApp.main(MainApp.java:11)
How can I get around this?
The simple fix is to change this line
Object[] slice = new Object[end - start];
to
Comparable[] slice = new Comparable[end - start];
The business of casting to T[] is a hack. It doesn't actually change tbe type of the array. You don't want to be passing it around pretending that it really is correctly typed. It may be clearer to use Object[] (or Comparable[]) or just plain old List<T>.
You can't even do the following:
Object[] a = new Object[] {1,3,4,5};
Integer[] b = (Integer[])a;
System.out.println(Arrays.toString(b));
This is because there is no guarantee that Object[] a doesn't really look like the following:
Object[] a = new Object[]{1,3,4,5.7}
Which clearly is not an array of Integer. But you could do this.
Object[] a = new Integer[] {1,3,4,5};
Integer[] b = (Integer[])a;
System.out.println(Arrays.toString(b));
The problem is that an array of Object isn't an array of Comparable. You need the slice array to have the same element type as the arr array. You can achieve this by changing
Object[] slice = new Object[end - start];
to
T[] slice = java.lang.reflect.Array.newInstance(arr.class.getComponentType(), end - start);
In other words, use reflection to determine at runtime the element type, and create slice arrays of the same type.
Using reflection is likely to be less performant, however. For an in-place sort algorithm like QuickSort, you shouldn't need to create any new arrays at all, you could just use the input array. (Or clone it, if you aren't allowed to modify the input.)

ArrayList's toArray() Method not Working Properly

When looking through ArrayList's methods, I saw a method called toArray(). I tried out this method using the following code:
ArrayList<Integer> a = new ArrayList<>();
// Assigning random elements to the ArrayList
int[] b = a.toArray();
However, this showed the following exception in the compiler:
Incompatible types.
Required: int[]
Found: java.lang.Object[]
The next thing I tried next is down-casting it to int[]
ArrayList<Integer> a = new ArrayList<>();
// Assigning random elements to the ArrayList
int[] b = (int[]) a.toArray();
This showed another error:
Cannot cast java.lang.Object[] to int[]
The last thing I tried is making it an Integer[] instead, and down-casting it to Integer[]
ArrayList<Integer> a = new ArrayList<>();
// Assigning random elements to the ArrayList
Integer[] b = (Integer[]) a.toArray();
This one compiled, but as soon as I ran it it produced ClassCastException. How do I use this toArray() method without errors?
List can only hold reference types (like Integer). Integer is a wrapper type. To convert a List<Integer> to an int[] there is an option using a Stream to map the Integer values to int and then collect to an int[]. Like,
int[] b = a.stream().mapToInt(Integer::intValue).toArray();
System.out.println(Arrays.toString(b));
It's all written in the javadoc:
Integer[] b = a.toArray(new Integer[0]);
Extending the answer of #Matthieu, It seems you need to pass new Integer[]. Attaching an example link given in geeksforgeeks.
Integer[] arr = new Integer[a.size()];
arr = a.toArray(arr);

Trying to cast setInstance.toArray() to Integer[], no compile time error but there is run time error, why?

I'm experimenting with Java HashSet class and its toArray() method. Below is the code I have came up with. The compiler did not display any error but when I run the code, the IDE outputs the error message:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
at JTOCollection.TheCollectionInterface.main(TheCollectionInterface.java:26)
Java Result: 1
Due to my inexperience, I can't fully understand the complete reason behind the error message, could someone please explain it to me?
Set<Integer> set1 = new HashSet<>();
set1.add(1);
set1.add(2);
set1.add(3);
set1.add(2);
Integer[] intArray = (Integer[]) set1.toArray();
for(Integer i : intArray){
System.out.println(i);
}
because you are using public Object[] toArray() instead of public <T> T[] toArray(T[] a).
use this:
Integer[] intArray = set1.toArray(new Integer[set1.size()]);
docs for : public <T> T[] 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.
If the collection fits in the specified array, it is returned therein.
Otherwise, a new array is allocated with the runtime type of the
specified array and the size of this collection.
set1.toArray() is an Object[] and cannot be cast to an Integer[]. If you want to have an Integer[] try this:
Integer[] intArray = set1.toArray(new Integer[set1.size()]);
Method set1.toArray() return Object[], you need to explicitly cast every object in returned array to Integer. Below code will work for you.
Set<Integer> set1 = new HashSet<>();
set1.add(1);
set1.add(2);
set1.add(3);
set1.add(2);
Object[] intArray = set1.toArray();
for(Object i : intArray){
System.out.println(i);
}

casting integer array to object array in java

I am using JDK 1.6 but the second line in the following snippet gives a compile error in Eclipse:
long[] css = new long[]{1, 2, 3};
Object[] objs = Arrays.copyOf(ccs, ccs.length, Object[].class );
Error is: The method copyOf(long[], int) in the type Arrays is not applicable for the arguments (long[], int, Class)
Casting is required for
org.hibernate.criterion.Restrictions.in("PropertyName", objs );
Any ideas or recommended approach?
TIA.
You can't do that in the java. long is a primitive type, and does because of that not extend Object. Long, which is a wrapper class for long, does and can be cast to an Object. To create a Long[] from a long[] you will need to go through every value of long[] and copy that to Long[]:
long[] primitiveLong;
Long[] wrappedLong = new Long[primitiveLong.length];
for (int i=0; i<primitiveLong.length; i++) {
wrappedLong[i] = primitiveLong[i];
}
Then you can cast it to an array of Object:
Object[] objs = wrappedLong;
Or you can even make the wrappedLong of type Object directly so you don't need the casting.
Use Apache Commons' ArrayUtils.toObject which does exactly this.

Downcasting from Object to Integer Runtime Error: java.lang.ClassCastException

Run time exception-- java.lang.ClassCastingException...
Integer intArr[] = new Integer[arrList.size()];
ArrayList <Integer> arrList =new ArrayList();
intArr=(Integer[])arrList.toArray(); // returns Object class which is downcaste to Integer;
I understand down-casting is not safe but why is this happening?
I also tried to converting ArrayList to String to Integer to int, but I get the same error.
Try to do this
intArr = arrList.toArray(new Integer[arrList.size()]);
What you get is a typed Integer Array and not a Object array.
First of all, this doesn't bind the ArrayList to type Integer.
ArrayList <Integer> arrList =new ArrayList();
Instead, this is what happens, arrList is assigned to an ArrayList of raw type, but that isn't a problem.
The problem lies in,
intArr=(Integer[])arrList.toArray();
since arrList is a raw-type (due to the assignment, it gets assigned as new ArrayList<Object>() by the compiler), you're effectively getting an Object[] instead.
Try assigning arrList to new ArrayList<Integer>() and do this:
intArr = arrList.toArray(new Integer[arrList.size()]);
The problem here is that you are trying to convert an array of objects to an array of integers. Array is an object in itself and Integer[] is not a sub-class of ArrayList, nor vice versa. What you have to do in your case is cast individual items, something like this:
Integer intArr[] = new Integer[arrList.size()];
for(int i=0; i<intArr.length; i++)
{
intArr[i] = (Integer)arrList.get(i);
}
Naturally, you may get ClassCastException if individual elements in the array list are not of type Integer.
toArray(T[] a) takes a paramter:
"a - the array into which the elements of the list are to be stored, if it is big enough; otherwise, a new array of the same runt"

Categories

Resources