tags:

views:

883

answers:

2

Take the following generics example

import java.util.List;
import java.util.ArrayList;

public class GenericsTest {
    private List<Animal> myList;

    public static void main(String args[]) {
        new GenericsTest(new ArrayList<Animal>()).add(new Dog());
    }

    public GenericsTest(List<Animal> list) {
        myList = list;
    }

    public void add(Animal a) {
      myList.add(a);
    }

    public interface Animal {}
    public static class Dog implements Animal {}
    public static class Cat implements Animal {}
}

It works fine. But as you know, you cannot construct it with

new GenericsTest(new ArrayList<Dog>());

because, as you know, the add(Animal) would make possible to add Cats. The suggested way of solving this problem, i.e. wildcarding does not work either, because, yes, you can change every List<Animal> in List<? extends Animal> but it has the same problem: you can create the GenericsTest with List<Cat> and then add Dogs.

So my question is: is there a convenient way to write this class once, and then use it for all the possible Animals? Of course it should solve straightforwardly the above mentioned problem.

+4  A: 

If I understand what you're trying to do then you need to put the generic type at class level:

public class GenericsTest<T extends Animal>
{
  private List<T> myList;

  public static void main(String args[])
  {
    new GenericsTest<Dog>(new ArrayList<Dog>());
  }

  public GenericsTest(List<T> list)
  {
    myList = list;
  }

  public void add(T a)
  {
    myList.add(a);
  }
}
Greg Cottman
Right. My actual code is more complex, because my Animals are actually List<V> and <T extends List<V>> does not seem to work, but that would be the my next question (if I don't figure out by myself)
Davide
+2  A: 

You may want to make the whole class generic rather than only the parameters:

import java.util.List;
import java.util.ArrayList;

public class GenericsTest<T extends Animal> {
    private final List<T> myList;

    public static void main(final String args[]) {
        new GenericsTest<Animal>(new ArrayList<Animal>()).add(new Dog());
        new GenericsTest<Dog>(new ArrayList<Dog>()).add(new Dog());
        new GenericsTest<Cat>(new ArrayList<Cat>()).add(new Cat());
    }

    public GenericsTest(final List<T> list) {
        myList = list;
    }

    public void add(final T a) {
      myList.add(a);
    }
}

// Can't nest as Animal needs to be in scope of class declaration
interface Animal {}
class Dog implements Animal {}
class Cat implements Animal {}
Diastrophism