Autoboxing
I have stayed away from autoboxing so far, probably because I have a vague feeling of losing control of the performance of my code. I don’t think it is justified, though, so autoboxing can come in handy and make your code a little bit more readable. I think I would encourage developers to flag their code when such autoboxing is happening, and I am pretty sure that IDE’s will soon be able to do the same.
Generics
Where to start?
Well, first of all, nobody can dispute that Generics are a solid concept that tends to improve the robustness of your code. The reason why they are so usually controversial regardless of the language is because of their implementation. And for having been a member of the C++ committee for many years , I can definitely vouch for the difficulty of getting them right.
In a nutshell, I have this to say about Java generics: my code feels more robust, but it’s harder to read.
So what’s the problem?
Redundancy.
First of all, I have always had a hard time with the redundancy introduced by the necessity of casting in general. For example, instead of writing:
Map accounts = new HashMap(); // no generics ... Account a = (Account) accounts.get("Cedric");
why can’t I just write:
Map m = new HashMap(); // no generics ... Account a = m.get("Cedric");
and let the compiler introduce a silent cast, since obviously, it’s an object of type Account that I am trying to retrieve from the Map?
Obviously, Generics don’t solve this problem entirely but they make a decent job at alleviating it somewhat. But they also make it worse in some other ways:
Map<String, List<Account>> accounts = new HashMap<String, List<Account>>();
Ouch.
Not only is the code significantly harder to read, but it fails to obey the DRY principle (“Don’t repeat yourself”). What if I need to change the value type of this map from List<Account> Collection<Account>? I need to replace all these statements everywhere in my code. While IDE refactoring will help, it’s still an awful lot of code for a modification of this kind that hardly impacts the semantics of this code.
Admittedly, there is no nice way to avoid this syntax when you are creating a new object, but what I am driving at is that I think Generics would have been better off if typedefs had been introduced with them.
Or so I thought at first.
But after thinking about it more, I realized that typedefs were the wrong solution to the problem, because simply put, they don’t add anything to the use of a separate class to define your complex Generic type.
class AccountMap extends HashMap<String, List<Account>> { ... }
Except for the fact that you need to extend an implementation (HashMap, and not Map, obviously), this solution is probably better than introducing typedef, which has its own quirks.
I haven’t gone to this trouble so far, but my recommendation would be: do it if you write the type more than three times (twice in the initialization and you use it more than once in your code).
Except for this little annoyance, I am quite happy with Generics overall and I particulary enjoy reading the TestNG Javadocs so nicely typed.
Conclusion
I am very happy with the new features of JDK 5.0 and I am quite proud to have had a chance to influence it with my participation in JSR 175 and JSR 201. Like all radical evolutions, not all of the new features will be popular with everyone, but as long as most developers find some of these features useful and that backward compatibility is preserved, I think JDK 5.0 is a very solid step toward more solid Java code.
#1 by Zohar on September 22, 2004 - 4:40 am
Cedric,
The first non generic version has a Map of Account with a String key.
The generics version has a Map of List of Account with a String key.
#2 by dave on September 22, 2004 - 4:53 am
FYI, IDEA already ships with the ability to flag auto-boxing and auto-unboxing.
#3 by Frank Bolander on September 22, 2004 - 9:24 am
Since we’re talking radical evolutions, I wish Sun would step up the numerics of the JDK 5.0(ie extended precisions, more performant numerical libraries,etc.) Marshalling BigDecimals around is a PITA.
#4 by Shai Almog on September 22, 2004 - 10:04 am
Cedric: Well, first of all, nobody can dispute that Generics are a solid concept that tends to improve the robustness of your code.
Well, I disagree. Generics are a redundant feature and Java has been easier and just as useful as C++/C# without them so I think this is proof enough.
Generics skyrocket the complexity when dealing with polymorphism and various other complex use cases. Not to mention code readability, how even the JavaDoc isn’t as readable as it used to be etc…
The Java implementation of generics is so bad… I think this is the main reason Joshua Bloch ran away from Sun, he knew people will start throwing rotten fruit on him in conventions when they start running into the “issues” with this implementation.
People always say “casting is evil”, this is true for C++ where your application can crash and burn with no explanation… This is not as accurate in a dynamic runtime typesafe language such as Java. It should be modified to: “There are worse things than casting… Such as a crappy implementation of generics, or added complexity…”
Cedric: why can’t I just write:
Account a = m.get(“Cedric”);
You are afraid of auto boxing and not of automatic casting???
I would rather have a verbose language, its easier to read and grep. The fewer constructs we have in the language the better. Sure its a matter of opinion but it seems to me like inconsistency?
#5 by Jonathan Aquino on September 22, 2004 - 1:27 pm
[ why can’t I just write: … Account a = m.get(“Cedric”); ]
Groovy to the rescue! (or JRuby or Jython or BeanShell …)
#6 by Kirk on September 23, 2004 - 1:34 am
Hey Cedric,
Interesting blogging software. It tagged my response as containing questionable content. Are you trying to censor those that are speaking out against generics? 😉
I
#7 by Calum on September 27, 2004 - 4:48 am
“why can’t I just write:
Map m = new HashMap(); // no generics
…
Account a = m.get(“Cedric”);”
I thought that was the main point of generics – that you could get type-safe access without casting.
In this scenario, what’s to stop me doing:
Bank b = m.get(“Cedric”);
(introducing a silent cast to Bank) and getting a ClassCastException at runtime, as the object is actually an Account?
If the compiler’s going to allow you to remove casts, it needs to know what’s allowed and what’s not allowed, and basing it on one particular call to the map doesn’t seem too robust IMO.
#8 by Infernoz on September 29, 2004 - 12:14 pm
I think typedefs is definitely the answer for generics collections and the typed defs should be exposed by the .class file too, so that the compiler _knows_ what kind of composite collection is being passed into/out-of an object/class, otherwise the whole charade falls flat on it face for compiled library code! A bonus of the .class approach maybe that _proper_ generics would be possible, not the current half-arsed solution.
#9 by Sam Pullara on October 4, 2004 - 11:53 am
I’m glad Cedric has come around to my way of thinking 🙂 Must be the Google juice:
http://www.javarants.com/C1464297901/E1994239229/index.html
Sam
#10 by Isaac Gouy on November 15, 2004 - 7:45 am
“there is no nice way to avoid this syntax”
Sure there is!
HashMap<String, List<Account>> accounts = new HashMap();
let L1 = accounts.get(“Cedric”);
?List<Account> L2 = accounts.get(“Cedric”);
Nice is statically type-checked with local-type-inference, and compiles to standard JVM bytecode.
http://nice.sourceforge.net/
#11 by anr on December 8, 2004 - 9:32 pm
sdfgg
#12 by blacxcom on January 7, 2010 - 7:00 am
Very nice article about JDK 5.0
#13 by Anonymous on January 7, 2010 - 7:02 am
Nice article about JDK 5.0 in practice
http://blackbookcarvaluesx.com/tags/auto