DEV Community

Pains of Java generics solved in Kotlin

Pavol Rajzak on September 06, 2018

The problem Why does this not compile in Java? Optional<Integer> optionalInteger = Optional.of(1); Optional<Number> opt...
Collapse
 
voins profile image
Alexey Voinov

I think you're missing a point here. Uncle Bob described this problem, but he used List<Shape> and List<Circle> I believe. Where Shape is a parent class for a Circle, obviously. I don't remember where it was exactly, maybe in one of his Clean Coder videos. The point is, even though Shape and Circle are related, List<Shape> and List<Circle> are not. And one is not a substitute for another. It is even dangerous, since that way you could add some other shape to what you think is a List<Shape> but really is List<Circle>, which could break your program. Reduced to absurdity: you and your spouse are related, but your lawyers (in case of divorce, for example) are not. :)

With that in mind, I believe the correct Java solution would be:

Optional<Integer> optionalInteger = Optional.of(1);
Optional<Number> optionalNumber = Optional.of(optionalInteger.get());

Or even

Optional<Integer> optionalInteger = Optional.of(1);
Optional<Number> optionalNumber = Optional.ofNullable(optionalInteger.orElse(null));

And about Kotlin... I wonder how would Kotlin behave in the case with Lists above? :)

Collapse
 
rapasoft profile image
Pavol Rajzak

With all respect I think you've missed the point of the article. Of course it does not apply to Lists, since they both produce and consume objects. It could apply to immutable lists, where you cannot add/set items, only get.

My point was to show that classes with generic types that are used in producer role are not detected by Java compiler as safe to cast, when covariant types are used.

Collapse
 
voins profile image
Alexey Voinov

I see. Thanks for the clarification. I'm still not sure that this technique is really safe and won't be abused in some very unobvious ways, but that's completely different story. :)