- What's so ugly about explicit type parameters?
- Done with inference!
- Let's pave the way for reification and promote explicit type parameters!
But all these compiler language terms, are showing off for no reason. The problem is not so complicated, but the stakes are high. Like Eric Burke says in his blog A Syntax Trick I Was Not Aware Of, there is a syntax in Java that very few people use and encounter: Explicit type arguments or parameters. One of the rare places where you may have encountered it, is in the JLS and javac code and test code. So, it looks like:
List<String> empty = Collections.<String>emptyList();The first reaction, for most Java developers, is: WTF?!
But I remember the first time I started converting some 1.4 code to use generics and wrote:
Map<Integer, Map<String,Thing>> messages;Wow, that's a lot of <>! And when I saw the amount of bugs the compiler gave me (wrong casting and objects in put()), I really thanked the <>, and asked for more ;-)
Why, the Java compiler wants to hide <> of explicit type parameter?
On IntelliJ the <String> before the emptyList method, is underlined with the remark: Explicit type arguments can be inferred. Basically, it means the compiler can be smart enough to replace the content of <> with the correct type. Great, at first. But wait?
Like Stephan says in Explicit Static Types are not for the Compiler, but for the Developer - Duh, the compiler knows a lot more stuff. He can remove a lot of all this types we are writing.
I love strongly type Java, and all the types repetition. I love the types in the code because it's more readable.
Question: Why explicit type parameters are an exception?
Answer: It got the Ugly Duckling stamp for some reason! Some said that it was dangerous for kittens!
Personally, I think there are 2 reasons:
- When Java 5 came out it looked like too much <> all over and Sun tried to remove some unneeded ones.
- It lacks consistency. I would really like to know, why explicit type parameters are declared BEFORE the method name? When, in constructor and type declaration, they are declared AFTER. In the later, they are enforced, and everybody is using them!
Another worrying inconsistency that may appear in Java 7 is around the "Short instance creation" issue. For example the nicest proposal so far is Neal's constructor type inference. I really like this proposal because it enables inference to work, but you SEE it working. It's not hidden woodoo compiler stuff. According to this proposal instead of:
List<String> list = new ArrayList<String>();you'd write:
List<String> list = new ArrayList<>();
Again, a strange sense of peculiarity for the method emptyList. In the type inference block of Alex Miller Java 7 page, you see the peculiar treatment of methods compare to types.
Why nobody wants:
List<String> empty = Collections.<>emptyList();It's the same, no? Let's be consistent!
Now, the main big issue that I have with this inference vs. explicit issue, is that it's moving Java away from reification of generics. It's going in the wrong direction. I just refactored some JPA code from:
// The Class of the bean implementaion provided byto
// the framework and unknown to the client
Class implClass = ...;
MyBeanInterface b = (MyBeanInterface) em.find(implClass,pk);
MyBeanInterface b = em.<MyBeanInterface>find(implClass,pk);It may be just changing casting to generics. But that's the point of generics being way nicer and more powerful.
The other point is, when generics will be reified I'd be closer to the perfect methods:
MyBeanInterface b = em.<MyBeanInterface>find(pk);These methods will find the implementation from the interface. Exactly what I need, the client code doesn't know about the implementation class, and the code is very clean and readable.
or with VISIBLE type inference
MyBeanInterface b = em.<>find(pk);
Today, because of erasure, in most methods (80%) that use generic types, you end up having Class<T> or Collection<T> as a parameter. So, inference works most of the time, and it's saving us from having to visualize the Ugly Duckling. For sure, it worked.
Now, for the 20% that still resist the roman empire of javac guru inference power, a new wave is coming. They want to write a "smarter" javac, that will make inference work (Check Kevin Bourrillion and Bob Lee comments here).
Here, there is a shift in the javac thinking, and it's going against readability, since: The "smarter" (or magical) the compiler is, the less "readable" your code is. Furthermore, inference will never be (by definition) 100% sure. So, why bother? The final code is more readable anyway...
IMHO: The kittens are safe, and reifying generics is more important than inference.