Home > Programming > Java Anti-Patterns revisited

Java Anti-Patterns revisited

Today I’ve stumbled over an interesting Homepage that contains a section about Java Anti-Patterns. It’s really well written and funny to read. Unfortunately it also contains some advises that I cannot agree with at all:

Lists are overrated: I would say quite the opposite: Prefer lists to arrays unless you have a very good reason not to. Arrays might perform considerably better in some cases, but they are far more easily used incorrectly (because of a major design flaw) and don’t mix well with generics. Also, programming against the List interface is more convenient and adds an additional layer of abstraction that allows you to change the actual List implementation easily. EffJava2 dedicates Item 25 to this topic alone.

Hashtable, HashMap and HashSet are overrated: I cannot agree here too: Yes, the entry wrappers are bigger than one might initially expect as they contain an additional forward reference and a cache for the hash code. And yes, HashSet is in fact implemented using a HashMap. I have to admit that this made me a bit curious, so I looked at the corresponding implementations in libstdc++ for unordered_map and unordered_set. What I found out is that they are using basically the same entry wrappers, although they let you decide with a C++ template parameter if the hash code is cached, which is false by default. Here is a comment found in one of the related headers:

// Nodes, used to wrap elements stored in the hash table. A policy
// template parameter of class template _Hashtable controls whether
// nodes also store a hash code. In some cases (e.g. strings) this
// may be a performance win.

To be fair however, it should be noted, that the C++ implementation does not waste a pointer if caching is disabled. Also, although they too use a shared implementation for unordered_map and unordered_set, C++ templates allows them to do this without wasting any space for sets, or doing lots of casting (which would be unavoidable if one tried the same approach in Java). To cut a long story short: The implementations that are shipped with the Java standard library aren’t that bad at all, they just reflect the fact that Java isn’t C++, which features a turing complete, code generating metalanguage via the template mechanism, that looks like Java generics only on the surface. Should your analysis reveal that the Java implementations of HashSet and HashMap generally (not only in a few hotspots) waste too much space, then most likely Java isn’t the right tool for your task at all. Otherwise just use HashMap and HashSet and don’t care about the memory overhead, which isn’t that bad as long as you don’t store small objects in these containers. Using exotic Map implementations like IdentiyHashMap is the right thing to do only in rare occasions, because IdentiyHashMap intentionally violates Map‘s general contract which is normally not what you want.

Not properly propagating the exception: Here the author claims that you may loose information if you do

catch(SomeException e)
    throw new RuntimeException(e);

instead of

catch(SomeException e)
    throw new RuntimeException(e.getMessage(), e);

which is true in theory for the detail message of the constructed RuntimeException, but should happen in practice only if SomeException overrides Throwable.toString() or Throwable.getLocalizedMessage() in a rather obscure way. I’m not aware of any exceptions that do this (and if I was I would rather fix them), but maybe I missed something, so please correct me if I’m wrong.

Too much static: In this item the author makes an interesting point about storing loggers in static fields prevents unused classes from being garbage collected. This sounds perfectly reasonable and caused me some headaches as I always store loggers in static fields. Some research however revealed, that it is not true. Let me cite the relevant part from the Java Language Specification:

A class or interface may be unloaded if and only if its defining class loader may be reclaimed by the garbage collector as discussed in §12.6. Classes and interfaces loaded by the bootstrap loader may not be unloaded.

So abandoning static loggers won’t change anything as far as class unloading is concerned. Storing loggers in normal instance fields on the other hand side can be annoying in entity beans and can cause screwups with serialization, as correctly pointed out in The transient trap. So my advice here is: Just store your loggers in private static final fields, and be done with it. Should you ever have the need to access the logger of a superclass, you can still obtain it explicitly by something like

Logger log = LoggerFactory.getLogger(getClass().getSuperclass());

although I don’t know any usecase for this other than someone deliberately obfuscating the source of the log messages.

Categories: Programming Tags: , ,
  1. Odi
    December 11, 2009 at 20:43

    Thanks for the review. I have updated the article a bit. Better explanations what’s wrong with sets and lists, and why propagating Exception.toString() is worse then Exception.getMessage(). You are however completely right about the Logger stuff. I have replaced that paragraph with something that makes sense. Thanks!

    • December 13, 2009 at 04:49

      Thanks for the update! Your remarks about lists have made me curious, so I started doing some benchmarks. What I found out so far is that they can in fact be horribly inefficient, especially when comparing lists of boxed primitives to arrays of primitive types. So, my next blog post, which was planned continue my concurrency series, will most likely focus on collections and arrays only.

      I’d also like to make some small remarks on the updated versions of “Not properly propagating the exception” and “Log instances: static or not?”, but doing that here seems horribly inefficient. Have you ever thought of transferring your Anti-Patterns to http://javaantipatterns.wordpress.com/ where everybody can add comments to them individually?

  2. Odi
    December 14, 2009 at 18:32

    Oh, just email me. See Contact on my site.

  1. January 7, 2010 at 22:13
  2. January 7, 2010 at 22:22

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: