简体   繁体   中英

Error with return-statement of generic type function

I am trying to make a generic function into which I pass an array (int[], String[]) and gets back the sorted version of it using TreeSort. I haven't even had the chance to begin to debug it since the mainclass refuses to accept an int[] array as the parameter .

TreeSort

public T[] treeSort(T[] arr) {

  T[] result = (T[]) new Object[arr.length];

  for (int i = 0; i < arr.length; i++)
    if (arr[i] != null) 
      add(arr[i]);

  Iterator it = iterator();
  int count = 0;
  while (it.hasNext()) 
    result[count++] = (T) it.next();

  return (T[]) result;
}

Main

BinarySearchTree<Integer> tree2 = new BinarySearchTree<>();
int[] unsortedNums = {6,3,7,4,1,2,9,8,5};
int[] sortedNums   = tree2.treeSort(unsortedNums);

Error

The method treeSort(Integer[]) in the type BinarySearchTree is not applicable for the arguments (int[])

So I attempted to change unsortedNums and sortedNums from int to Integer (why should this matter?), and now running it yields this error:

Errorr 2

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;

on line

T[] result = (T[]) new Object[arr.length];

In a generic method in Java, it is not allowed to create an array of the generic type. You are trying to circumvent this rule by creating an Object array and casting it to the generic type, but the compiler is too smart and prevents this. The reason for this rule is that the generic type could well be an Interface, so the runtime wouldn't know which class to create.

For your example, if you really need to keep the unsorted array as it is and return a copy (usually, sorting happens in-place so you would just edit the original array), you can either let the user pass the type of the generic (as in sp00m's answer), or let the user supply the destination array as a parameter so you don't need to create an array yourself.

IMO, the best practice here would be to make your sorting happen in place instead of returning a sorted copy of the data.

Instead of:

T[] result = (T[]) new Object[arr.length];

You have to use:

T[] result = (T[]) Array.newInstance(clazz, arr.length);

Where clazz is the type of the nested elements:

public T[] treeSort(T[] arr, Class<T> clazz) {...}

Finally, when calling, use the boxed primitive:

Integer[] unsortedNums = { 6, 3, 7, 4, 1, 2, 9, 8, 5 };
Integer[] sortedNums = treeSort(unsortedNums, Integer.class);

In Java, arrays know their component types at runtime (the component type is part of the actual runtime array type), and thus you need to specify the component type at runtime to create an array of that type.

@spoom's answer showed you how to create the array given a class object passed into the function. However, you actually already have that information without passing it separately. The parameter arr is of type T[] , which means the array object's actual runtime type must be T[] or a subclass thereof. We can extract the component type from that and use it to create the new array:

T[] result = (T[]) Array.newInstance(arr.getClass().getComponentType(), arr.length);

This is how, for example, Arrays.copyOf() and related functions work.

You can't use primitive types (int) in generitcs. Try to use object wrapper, for example

Integer[] unsortedNums = {6,3,7,4,1,2,9,8,5}; Integer[] sortedNums = tree2.treeSort(unsortedNums);

Combining Generics and arrays is problematic in Java; check out the article Restrictions on Generics for details.

As to solving the problem, the easiest thing to do would be not using an array but rather a List. So for example:

public List<T> treeSort(List<T> list) {

    List<T> result = new ArrayList<T>(list.size());

    for (int i = 0; i < list.size(); i++)
        if (list.get(i) != null)
            result.add(list.get(i));

    Iterator<T> it = list.iterator();
    int count = 0;
    while (it.hasNext())
        result.set(count++, it.next());

    return result;
}

Mind you, I haven't tested the logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM