The following code is an example of what I hope to achieved. Unfortunately, there is no way to compile this code without a cast in the function getElements()
.
I still have quite wrapped my head around Java generics completely, but this seems like a fairly simply case to get around.
Any help would be greatly appreciated.
import org.junit.Test;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class GenericFruitTest
{
@Test
public void genericFruit()
{
Collection<Apple> apples = new FruitBasket().getApples();
Collection<Orange> oranges = new FruitBasket().getOranges();
Collection<Rye> rye = new BreadBasket().getRye();
}
class FruitBasket extends Basket<Fruit>
{
Collection<Apple> getApples()
{
return getElements(Apple.class);
}
Collection<Orange> getOranges()
{
return getElements(Orange.class);
}
}
private class BreadBasket extends Basket<Bread>
{
private Collection<Rye> rye;
public Collection<Rye> getRye()
{
return getElements(Rye.class);
}
}
class Basket<E>
{
Map<Class<? extends E>, Collection<? extends E>> classCollectionMap = new HashMap<Class<? extends E>, Collection<? extends E>>();
<T extends E> Collection<T> getElements(Class<T> elementClass)
{
// The following line throws compile time "incompatible types" without cast
return classCollectionMap.get(elementClass);
}
}
class Rye extends Bread
{
}
class Apple extends Fruit
{
}
class Orange extends Fruit
{
}
class Fruit
{
}
private class Bread
{
}
}
It requires a casting because the compiler doesn't know the type of the collection that any given key has. Your map says that it maps a Class
of an unkwnown type to a Collection
of an unknown type, but you have no way of telling the map that they have to be the same type.
When working with generics, most of the time you can't get rid of the casts. Most of those casts are, however, unchecked conversions that are removed at runtime because of type erasure. The point is that, when you can guarantee type safety, the compiler leaves you alone and clients of your class get a type-safe, casting-free interface.
Of course, if you screw up, the runtime has no way of alerting you.