They say it’s those little things in life. I believe the same is very much true for your code as well. Here’s an example with casting and generics in Java.
After a long hard day in the code editor I often find that what makes me happy about my day, and the work I check in to our SCM, is not always the additions to an advanced algorithm, or an insanely compact chunk of awesomeness, but it’s more often a small piece of beautiful code. One of the ugliest lines of code I see in Java, are lines involved with casting.
I recently started doing a bit of coding on a web application a couple of weeks back. Suddenly I found myself writing a lot of casting statements when fetching data from session, which made my code want to crawl out of the editor due to it’s own ugliness. Here is an example:
Session webappSession = ...
Map<String, Map<String, Collection<Entity>>> myUglyMap = (Map<String, Map<String, Collection<Entity>>>)(webappSession.getAttribute("myUglyMap"));
Oh boy! I figured there must be some other way to write this. With our static imports fever as of late I came up with a tiny piece of code which made me go home smiling that day. That little thing which made it all so much more beautiful…
public static <T> T cast(Object o) {
return (T) o;
}
Placed in a easily accessible class in your favourite toolbox project, the messy snippet above quickly becomes much better:
import static com.mydomain.CastUtils.cast;
/* snipp */
Session webappSession = ...
Map<String, Map<String, Collection<Entity>>> beautiful = cast(webappSession.getAttribute("beautiful"));


I would replace your highly generified Map with a tailor-made Java object. A good old FormBean hides casting – that said, I get your point. Static imports and generics really helps you write beautiful code.
Hmm, looks like quite handy.
+1 to creating another object.
I would suggest to create an adapter object that could wrap webappSession and give you the access methods to what you really need:
public class WebAppSessionAdaptor {
private Session session;
public Map<String, Map<String, Collection>> getBeautifulAttribute() {
return (Map<String, Map<String, Collection>>) session.getAttribute("beautiful");
}
}
This gives you following advantages:
- its less error prone as it adds type-checking. With your cast() you do not really have any type-checking and you’ll get runtime exception for every typo in used variable type.
- its less error prone as it contains internally attribute names. Now you wont get an error because of misspelling ‘beautiful’.
- it will work with primitive types
- its more readable – each method has a descriptive name
You should check Google Collections.
Instead of:
Map<String, Map<String, Collection>> myUglyMap = (Map<String, Map<String, Collection>>) (webappSession.getAttribute("myUglyMap"));You could have:
Map<String, Map<String, Collection>> myCoolMap = Maps.newHashMap();Exactly as implemented on a little open source project I cofounded: Fluent Java. Java has soo many of these kind of uneasyness, that the whole library manages to make them more fluent.
Another of my favourite ones is:
FluentSet agilesIntersection =
set(“tdd”, “planning”, “refactoring”)
.intersect(
set(“restrospective”, “planning”, “scrum of scrums”)
);
More here.
Thank you all for your feedback!
@ppow: I see your point if this was the only case, but you’re tying your solution very tightly with this specific case. You would have to write a separate method for every attribute you wanted to fetch from the session, which I would consider a unecessary overhead in many cases. The point here was to have a generic method which would cause very little additional coding and make the code a little cleaner in the cases where you have no choice but to use this complex data structure
As for type checking, aren’t you simply moving the location of a possible ClassCastException?
@orlandocr: Thanks, we’re well familiar with Google Collections and use it daily
You should check out our coverage of Google Collections and Guava, part 2 is coming up very soon. As for this case – where an object is fetched from session – Google Collection does not really solve the issue. Even if the data structure was constructed using the static method from Google Collections, I would still have to do the nasty cast when fetching it
@Daniel Ribeiro: Very cool! I was looking for other projects already providing this, unfortunately I did not discover yours.
@Daniel Ribeiro Hey, thanks for the link! Had FluentJava on my google code favorites but haven’t had the chance to check it out yet – will definitely do so now:) Cheers!
@Jaran Nilsen
There are so many java open source projects around, that finding one with a feature you are looking for is quite hard. Google Guava is one of the most known solvers of of java annoyances, and still is widely unkwnown. But both Guava and Google collections don’t solve some common tasks that Fluent Java does.
Interestingly enough, all of these annoyances are solved by Scala on its core language.
Hi..
Here is the code is given for the casting of Java code into Java Generics…
I will copied it for my future use..!!
Anyway Thanks for this Information….!!
Thanks for the nice code and please check my suggestion to make it better here: http://satukubik.com/2010/01/06/java-tips-using-generic-correctly/
Surely this is missing the point of what the compiler is warning you about, your ‘beautiful’ code is just moving the problem elsewhere.
Your original code has both an unchecked cast and an unchecked conversion. Seeing as neither are being checked you can write less code and get exactly the same bytecode by only coding the required cast i.e.:
Map<String, Map<String, Collection>> myUglyMap = (Map)webappSession.getAttribute(“myUglyMap”);
Which is the same length as your workaround without having to create an extra utility class and import it.
Now if you wanted to really address the problem you’d need to define the parameterised type Map in a custom class, then perform a checked cast on the object from the session map.
Failing that you could iterate over the contents of the map (and nested map, and collection) checking their types. Without this you are doing an unchecked conversion and should rightly by warned by the compiler- if the cast passes you may still get class casts down the line as other code accesses the data in the Map.