Alon
Alon

Reputation: 11

Generics and downcasting (java)

Been trying to find a straight answer/solution for this for the past 3 hours with no luck, hoping you guys can help:

I have the following classes which implement an interval tree using a binary search tree:

public class Node<T extends Comparable<T>> implements Comparable<Node<T>> {...}

public class BinarySearchTree<T extends Comparable<T>> {
protected Node<T> root;
...}

public class IntervalNode extends Node<Interval> {...}

public class IntervalTree extends BinarySearchTree<Interval> {...}

When I attempt the following cast on the root member of an instance of IntervalTree I get a ClassCastException:

IntervalNode CurrentNode = (IntervalNode)root; //root being of type Node<Interval>
which IntervalNode extends.

I'm fairly new to java but from what I've read and googled this downcasting should be possible so I'm kinda lost as to the cause of this exception. My best guess so far is that this is caused by type erasure but I haven't been able to find a straight answer on the matter. Any ideas as to the cause of this exception or better yet a workaround?

Upvotes: 1

Views: 1525

Answers (3)

trutheality
trutheality

Reputation: 23455

If you make Node an interface (and possibly put common implementation in a base class), you could do almost exactly what you were trying to do in the first place:

public interface Node<T extends Comparable<T>> extends Comparable<Node<T>> {...}
public class BaseNode<T extends Comparable<T>> implements Node<T> {...}

public class IntervalNode extends BaseNode<Interval> implements Node<Interval> {...}

Everything should work fine as long as you make all the Nodes IntervalTree uses instances of IntervalNode.

Either way (with or without interfaces) you need to make sure to override anything in BinarySearchTree that creates Nodes in IntervalTree to create IntervalNodes.

Upvotes: 0

Mike Valenty
Mike Valenty

Reputation: 8991

If you need an IntervalNode in your IntervalTree, then how about:

public class BinarySearchTree<T extends Node<?>> {
    protected T root;
}

public class IntervalTree extends BinarySearchTree<IntervalNode> {

}

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 692201

You're not upcasting here, but downcasting. An IntervalNode is a Node<Interval> (because it extends it), but a Node<Interval> is not necessarily an IntervalNode.

Just as a Banana is a Fruit because it extends it, but a Fruit is not always a Banana. If you have a Fruit and cast it to a Banana, it will work only if the fruit is effectively a banana. If it's an apple, it will fail.

Upvotes: 7

Related Questions