Gustavo Sousa
Gustavo Sousa

Reputation: 35

Cannot cast Object to Comparable

I'm trying to order a binary search tree, and store its values on an array, but when I try to convert my ArrayList to array it says I cannot convert an Object to Comparable.

@Override
public T[] postOrder() {
    ArrayList<T> array = new ArrayList<T>();
    postOrder(root, array);
    return (T[]) array.toArray();
}

private void postOrder(BSTNode<T> currRoot, ArrayList<T> array) {
    if (currRoot == null)
        return;
    if (!currRoot.getLeft().isEmpty())
        postOrder((BSTNode<T>) currRoot.getLeft(), array);
    if (!currRoot.getRight().isEmpty())
        postOrder((BSTNode<T>) currRoot.getRight(), array);
    array.add(currRoot.getData());
}

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

edit: solved that way

public T[] postOrder() {
    ArrayList<T> array = new ArrayList<T>();
    postOrder(root, array);
    return array.toArray((T[]) Array.newInstance(root.getData().getClass(), size()));
}

Upvotes: 2

Views: 4755

Answers (2)

Radiodef
Radiodef

Reputation: 37845

[Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;

This means you are trying to cast Object[] to Comparable[]. (The "[L" means array.)

toArray returns Object[]. You may be able to use <T>toArray(T[]) instead; however, due to type erasure you cannot do

//                  cannot do
//                    vvvvv
return array.toArray( new T[ mySize ] );

So either

  • Your tree needs a Class<T>.
  • The caller needs to pass a T[] to fill.
  • postOrder needs to return a non-generic array. (Object[]... Comparable[]...)
  • You should return a List<T> instead of a T[].

I notice you are using @Override so maybe your supertype (interface, superclass) has instructions on how to implement this method. (i.e. if this is homework you should ask your instructor because it is not clear to me which solution you should use.)

If you happen to have a Class<T>, then you can do

@Override
public T[] postOrder() {
    ArrayList<T> array = new ArrayList<T>();
    postOrder(root, array);
    return (T[]) array.toArray(
        java.lang.reflect.Array.newInstance(myClassT, array.size())
    );
}

Otherwise you need to change the signature of the method.

See also

Upvotes: 4

TWiStErRob
TWiStErRob

Reputation: 46470

Generic arrays are messy, you need to call the other toArray() method:

public T[] postOrder(T[] result) {
    ArrayList<T> array = new ArrayList<T>();
    postOrder(root, array);
    return array.toArray(result);
}

It doesn't matter what size the result is, just make sure you don't use later what you passed in, because it may get reallocated inside toArray if the size is not correct, so use only the return value of postOrder.

Consider that it's probably much much more cleaner if you just return List<T>, and let the caller take care of converting it to an array! Notice how much less explanation is needed for returning a List...

public List<T> postOrder() {
    ArrayList<T> array = new ArrayList<T>();
    postOrder(root, array);
    return array;
}

Upvotes: 2

Related Questions