Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you deal with "super" generics in java?

Tags:

java

generics

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.

like image 496
Davide Avatar asked Oct 21 '08 23:10

Davide


2 Answers

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);
  }
}
like image 186
Greg Cottman Avatar answered Oct 05 '22 04:10

Greg Cottman


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 {}
like image 32
Diastrophism Avatar answered Oct 05 '22 04:10

Diastrophism