1

I was playing around with generics and now I am curious why I need to cast the "new Special()" to E before adding it to the Set. I know that this is not really needed in this case, because I could use a Set of Base as well...

private static class Base {}
private static class Special extends Base{}

private <E extends Base> Set<E> doSomething(){
    Set<E> someset = new HashSet<>();
    someset.add(new Special());
    return someset;
}
Daniel
  • 874
  • 10
  • 31

2 Answers2

3

Suppose you had this:

final class SomethingElse extends Base {}

and this:

private <E extends Base> doSomething(Set<E> someset) {
   someset.add(new Special());
}

Can you see the problem now?

E extends Base means that "E is an unknown type that extends Base". It doesn't mean "E is any type that extends Base."

In the example above, the problem is that one could call doSomething() like this:

Set<Special> onlySpecials = new HashSet<>();
doSomething(onlySpecials);
onlySpecials.stream()
  .findFirst()
  .ifPresent(Special::someSpecializedMethod); /* Boom! ClassCastException! */
erickson
  • 265,237
  • 58
  • 395
  • 493
1

Imagine that Base have two subtype: Special and VerySpecial. And you call doSomething like this:

Set<VerySpecial> set = doSomething();

In this case your set will contain Special instance which is not what you expected because its type don not allow that.

talex
  • 17,973
  • 3
  • 29
  • 66