Java Generics

When you would have multiple almost identical classes that only differ by an inner type then maybe generics are a way for you to avoid code duplication

class Foo<T>
{
  private T val;

  void setValue( T val )
  {
    this.val = val;
  }

  T getValue()
  {
    return val;
  }
}

Foo<String>  stringFoo = new Foo<String>();
Foo<Integer> intFoo    = new Foo<Integer>();
Foo<Point>   pointFoo  = new Foo<Point>();

Also works for methods only

class Bar
{
  public static <T extends Number> T myMethod( T a, T b, HashMap<T, String> )
  {
   //...
  }
}

Inherite from a super class that uses generics without further restricting the generic type

public class Bar<T> extends Foo<T> { ... }

If you mess this up you might get this error

A supertype may not specify any wildcard

This is an example how to restrict the type when you inherite from a class using generics. Here we have a simple hierachie of different types of dogs

public class Dog
{
    public void bark()
    {
        System.out.println("Wuff!");
    }
}

public class Poodle extends Dog
{
    public void barkLikeAPoddle()
    {
        System.out.println("Wuff, Wuff!");
    }
}

public class FrenchPoodle extends Poodle
{
    public void barkLikeAFrenchPoddle()
    {
        System.out.println("Wüff, Wüff!");
    }
}

And now we have another hierachie that uses the first one

public class DogHouse<T extends Dog>
{
    public class DogHouse() {
      this.dogInTheHouse=...; // (1)
    }

    protected T dogInTheHouse;

    public void wakeTheDog()
    {
        this.dogInTheHouse.bark();
    }
}
  1. The constructor or in general initializations are tricky.
 this.dogInTheHouse=new Dog();          // Fails because T might be Poodle
 this.dogInTheHouse=new Poodle();       // Fails because T might be FrenchPoodle
 this.dogInTheHouse=new FrenchPoodle(); // Fails because T might be a dog which is not a Poodle
}

Now lets say we want to restrict the dogs that can be used

public class DogHouseForAPoodle<T extends Poodle> extends DogHouse<T>
{  
    public void wakeTheDog()
    {
        this.dogInTheHouse.bark();
        this.dogInTheHouse.barkLikeAPoddle();
    }

    public void assignementIsEasy(T newDog)
    {
        this.dogInTheHouse=newDog;
    }

When we have a concrete type for T everything becomes easy again

public class DogHouseForAFrenchPoodle extends DogHouseForAPoodle<FrenchPoodle>
{
    public void wakeTheDog()
    {
        this.dogInTheHouse.bark();
        this.dogInTheHouse.barkLikeAPoddle();
        this.dogInTheHouse.barkLikeAFrenchPoddle();
    }
}