KIC KIC - 1 month ago 7
Java Question

Is there a way to deal with nested generics using Class<T>

If you look at the this vey simple code snipped, is there a valid way to actually call

baz
?

public class Foo {
static class Bar<T> {
public void baz(Class<? extends List<T>> cls) {

}
}

public static void main(String[] args) {
Bar<String> bar = new Bar<>();

// does not compile
bar.baz(ArrayList<String>.class);
bar.baz((Class<List<String>>) ArrayList.class);
bar.baz(new ArrayList<String>().getClass());
}
}

Answer

I can think of two ways (they both have their disadvantages):

1.

Bar bar = new Bar<>();
bar.baz(ArrayList.class);

This of course removes the String type parameter, which you might not want.

2.

Bar<String> bar = new Bar<>();
bar.baz(MyClass.class);

Here, MyClass is declared like a wrapper of ArrayList<String>:

class MyClass implements List<String> {
    private ArrayList<String> inner = new ArrayList<>();

    @Override
    public int size() {
        return inner.size();
    }

    @Override
    public boolean isEmpty() {
        return inner.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return inner.contains(o);
    }

    @Override
    public Iterator<String> iterator() {
        return inner.iterator();
    }

    @Override
    public Object[] toArray() {
        return inner.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return inner.toArray(a);
    }

    @Override
    public boolean add(String s) {
        return inner.add(s);
    }

    @Override
    public boolean remove(Object o) {
        return inner.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return inner.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends String> c) {
        return inner.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends String> c) {
        return inner.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return inner.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return inner.retainAll(c);
    }

    @Override
    public void clear() {
        inner.clear();
    }

    @Override
    public String get(int index) {
        return inner.get(index);
    }

    @Override
    public String set(int index, String element) {
        return inner.set(index, element);
    }

    @Override
    public void add(int index, String element) {
        inner.add(index, element);
    }

    @Override
    public String remove(int index) {
        return inner.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return inner.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return inner.lastIndexOf(o);
    }

    @Override
    public ListIterator<String> listIterator() {
        return inner.listIterator();
    }

    @Override
    public ListIterator<String> listIterator(int index) {
        return inner.listIterator(index);
    }

    @Override
    public List<String> subList(int fromIndex, int toIndex) {
        return inner.subList(fromIndex, toIndex);
    }
}

The disadvantage of this is of course, wasting time to create a brand new class that implements List<String>. If you are lazy, you can try extending AbstractList<String> instead.

Comments