ion20
ion20

Reputation: 657

Type casting in Java as a workaround to the absence of generic arrays

I have a class with a header defined as public class MaxPQ<Key extends Comparable<Key>>. Now, when I try making an array of Key, the way I do it in my constructor is as follows: Key[] pq = (Key[]) new Comparable[2]; This works fine but if I change Comparable to Object, I get an error. Why?

While in another code where the header looked like public class Stack<Item>, making an array of Item(s) like Item[] stack = (Item[]) new Object[1] worked just fine.

PS: I am following an online tutorial and this is what the code looks like:

public class MaxPQ<Key extends Comparable<Key>> {

private Key[] pq;
private int N;

public MaxPQ(int capacity) {
    pq = (Key[]) new Comparable[capacity + 1];
}

public void insert(Key key) {
    pq[++N] = key;
    swim(N);
}

public Key delMax() {
    Key key = pq[1];
    exch(1, N--);
    sink(1);
    pq[N + 1] = null;
    return key;
}

private void swim(int k) {
    while(k > 1 && less(k/2, k)) {
        exch(k, k/2);
        k = k/2;
    }
}

private void sink(int k) {
    while (2*k < N) {
        int j = 2*k;
        if (j < N && less(j, j + 1)) j++;
        if (less(j, k)) break;
        exch(j, k);
        k = j;
    }
}

private boolean less(int p, int q) {
    return pq[p].compareTo(pq[q]) < 0;
}

private void exch(int p, int q) {
    Key temp = pq[p];
    pq[p] = pq[q];
    pq[q] = temp;
}

Upvotes: 0

Views: 136

Answers (1)

JB Nizet
JB Nizet

Reputation: 691735

When a generic type has an upper bound, the erased type is that upper bound. That means that a class like

public class Stack<I> {
    private I[] array;
}

is in fact compiled to something like

public class Stack {
    private Object[] array;
}

whereas a class like

public class MaxPQ<Key extends Comparable<Key>> {
    private Key[] array;
}

is compiled to something like

public class MaxPQ {
    private Comparable[] array;
}

Thus, when executing

Key[] pq = (Key[]) new Comparable[2];

what is in fact executed is

Comparable[] pq = (Comparable[]) new Comparable[2];

which is fine. If you change it to Object[], you're in fact executing

Comparable[] pq = (Comparable[]) new Object[2];

which causes a ClassCastException, since an Object[] is not a Comparable[].

You should use a List<Key> instead of an array: you wouldn't have all these troubles.

Upvotes: 3

Related Questions