Why should I care that Java doesn't have reified generics?
The thing that most commonly bites me is the inability to take advantage of multiple dispatch across multiple generic types. The following isn't possible and there are many cases where it would be the best solution:
public void my_method(List<String> input) { ... }
public void my_method(List<Integer> input) { ... }
From the few times that I came across this "need", it ultimately boils down to this construct:
public class Foo<T> {
private T t;
public Foo() {
this.t = new T(); // Help?
}
}
This does work in C# assuming that T
has a default constructor. You can even get the runtime type by typeof(T)
and get the constructors by Type.GetConstructor()
.
The common Java solution would be to pass the Class<T>
as argument.
public class Foo<T> {
private T t;
public Foo(Class<T> cls) throws Exception {
this.t = cls.newInstance();
}
}
(it does not necessarily need to be passed as constructor argument, as a method argument is also fine, the above is just an example, also the try-catch
is omitted for brevity)
For all other generic type constructs, the actual type can easily be resolved with a bit help of reflection. The below Q&A illustrate the use cases and possibilities:
- Get generic type of java.util.List
- How to get the generic type at runtime?
- Get actual type of generic type argument on abstract superclass
Type safety comes to mind. Downcasting to a parametrized type will always be unsafe without reified generics:
List<String> myFriends = new ArrayList();
myFriends.add("Alice");
getSession().put("friends", myFriends);
// later, elsewhere
List<Friend> myFriends = (List<Friend>) getSession().get("friends");
myFriends.add(new Friend("Bob")); // works like a charm!
// and so...
List<String> myFriends = (List<String>) getSession().get("friends");
for (String friend : myFriends) print(friend); // ClassCastException, wtf!?
Also, abstractions would leak less - at least the ones which may be interested in runtime information about their type parameters. Today, if you need any kind of runtime information about the type of one of the generic parameters you have to pass its Class
along as well. That way, your external interface depends on your implementation (whether you use RTTI about your parameters or not).