2

I am getting ClassCastException. I was following this answer but did not get it right. Cast Object to Generic Type for returning
BubbleSort.java

import java.util.ArrayList;
import java.util.List;

public class BubbleSort<T extends Number> {

    public List<T> list;

    @SuppressWarnings("serial")
    public BubbleSort() {
        list = new ArrayList<T>() {
        };
    }

    public void add(T obj) {
        list.add(obj);
    }

    public void sort() {
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.size() - 1; j++) {
                if (list.get(j).intValue() > list.get(j + 1).intValue()) {
                    T swapElement = list.get(j);
                    list.set(j, list.get(j + 1));
                    list.set(j + 1, swapElement);
                }
            }
        }
    } 

    public <T> T getArray(Class<T> clazz){
        T[] returnArray = (T[]) list.toArray();
        return clazz.cast(returnArray);
}

}

MainPorgram.java

import java.lang.reflect.Array;


public class MainProgram {

    public static void main(String args[]){
        BubbleSort<Integer> bubbleSort = new BubbleSort<>();
        bubbleSort.add(new Integer(1));
        bubbleSort.add(new Integer(2));
        bubbleSort.add(new Integer(6));
        bubbleSort.add(new Integer(5));
        bubbleSort.add(new Integer(4));
        bubbleSort.add(new Integer(3));
        Class<Integer[]> intArrayType = (Class<Integer[]>) Array.newInstance(Integer.TYPE, 0).getClass(); 
        Integer[] sortedArray = (Integer[]) bubbleSort.getArray(intArrayType);
        for(int i = 0 ; i < sortedArray.length; i++){
            System.out.println(sortedArray[i]);
        }
    }

}

Console

Exception in thread "main" java.lang.ClassCastException: Cannot cast [Ljava.lang.Object; to [I at java.lang.Class.cast(Unknown Source) at BubbleSort.getArray(BubbleSort.java:32) at MainProgram.main(MainProgram.java:15)

Community
  • 1
  • 1
user6556461
  • 377
  • 3
  • 14
  • 1
    _"did not get it right"_ is insufficient. You are expected to post the stack trace and indicate which line in your program throws the exception. Also tell us what you've done to troubleshoot the problem. Did you step through the code in your debugger? – Jim Garrison Jan 18 '17 at 06:57
  • There are so many things wrong here. – shmosel Jan 18 '17 at 07:10
  • `(BubbleSort.java:32)` This means the error occurs on line 32 of BubbleSort.java. Which line is this? – Code-Apprentice Jan 18 '17 at 07:12
  • I don't think that the conversion with arrays works quite as you hope - and why not change it a bit - just do something like this instead: `Integer[] sortedArray = bubbleSort.list.toArray(new Integer[bubbleSort.list.size()]);` The problem is that the method getArray() always returns an array of objects, where the objects within that array is integer - however, you're expecting an array defined with Integer. Might be someone else may help you on how you can fix generics, however I don't see how. – vegaasen Jan 18 '17 at 07:19

3 Answers3

2

There's quite a bit of confusion and mistaken assumptions in your code. Instead of detailing all of them (some have been covered in other answers), I'll suggest a working approach that's much simpler, if you're on Java 8:

public class BubbleSort<T extends Number> {

    public List<T> list;

    public BubbleSort() {
        list = new ArrayList<T>();
    }

    //...

    public T[] getArray(IntFunction<T[]> arrayGenerator) {
        return list.stream().toArray(arrayGenerator);
    }
}

public class MainProgram {

    public static void main(String args[]) {
        BubbleSort<Integer> bubbleSort = new BubbleSort<>();
        //...
        Integer[] sortedArray = bubbleSort.getArray(Integer[]::new);
        //...
    }
}
shmosel
  • 49,289
  • 6
  • 73
  • 138
1

Cannot cast [Ljava.lang.Object; to [I at ...

The message may be confusing you. Here [Ljava.lang.Object; actually means the type Object[] and [I means int[]. These are Java type signatures which can be decoded according to https://stackoverflow.com/a/8066268/224671.


So the error message is complaining you are trying to cast an Object[] to an int[]. The only place where you referred to the int type is this line:

    Class<Integer[]> intArrayType = 
           (Class<Integer[]>) Array.newInstance(Integer.TYPE, 0).getClass(); 

The problem is you are using Integer.TYPE which returns the type of int, so the class you get will be Class<int[]>. To use the actual Integer class, write:

    Class<Integer[]> intArrayType = 
           (Class<Integer[]>) Array.newInstance(Integer.class, 0).getClass(); 
    //                                                  ^~~~~

(See Difference between Integer.class and Integer.TYPE for the difference.)

Note that since you already know that you will deal with Integer[] class, you don't need to call .getClass(), just this is enough:

Class<Integer[]> intArrayType = Integer[].class;

But this is still wrong, e.g. in

public <T> T getArray(Class<T> clazz){
    T[] returnArray = (T[]) list.toArray();

you will be asserting to get an Integer[][] (and more problems which I'm not gonna go in detail)... See @Eran's answer for the proper fix.

Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • You've only addressed part of the problem. It's still returning `Object[]`. – shmosel Jan 18 '17 at 07:22
  • This will only change the error to `Cannot cast [Ljava.lang.Object; to [Ljava.lang.Integer;` – Eran Jan 18 '17 at 07:24
  • That last edit is incorrect. It's true that `T[]` would be `Integer[][]`, but because of type erasure the cast is ignored. The problem is on the next line, where `list.toArray()` [returns `Object[]`](https://docs.oracle.com/javase/8/docs/api/java/util/List.html#toArray--), which can't be cast to `Integer[]`. – shmosel Jan 18 '17 at 07:47
0

You have several issues.

The main issue is that list.toArray() returns an Object[], and you can't cast it to an array of a different type. You should use <T> T[] toArray(T[] a) to get an array of the correct type.

Another issue with your code was that your generic parameter declared in the method <T> T getArray(Class<T> clazz) hides the generic parameter of the same name declared in the class level (class BubbleSort<T extends Number>).

Here's a suggested fix that works :

public T[] getArray(Class<T> clazz) {
    return (T[]) list.toArray((T[])Array.newInstance (clazz, list.size()));
}

....

Integer[] sortedArray = bubbleSort.getArray(Integer.class);
Eran
  • 387,369
  • 54
  • 702
  • 768