Sunday, November 8, 2009

Java on the Decline?

I attended the No Fluff Just Stuff conference in Reston, VA this weekend (http://www.nofluffjuststuff.com/home/main), and once again it was excellent. One fact that is becoming clearer is that Java really is on the decline. With languages like Groovy and Scala (and Clojure - though I have no firsthand experience with that so I can't give much input there) on the rise, why should we still use Java?

I've been using groovy for the last year or so and use it in both tests and production code. Groovy is growing in popularity very quickly since it is just a dialect of Java, and all Java code is valid in Groovy. Developers can "groovify" code as they become more familiar with the Groovy idioms.

Scala is a bit newer to me, but I'm becoming familiar with that as well. At first I wondering why I needed language that could be both functional and OO, but it quickly became familiar. The functional aspect of Scala (and some of these operations are available in Groovy too) works magic on collections. Mapping operations to collections is a really nice feature. Think of all the times in Java you write code that looks something like this:

List myList// assume this is initialized
for ( MyObj o : myList ) {
System.out.println("o = " + o);
}

whereas in scala, the same code can be written as:

myList.foreach(n=> println(n))

This is a simple example, but any function can be mapped to every element in the list, which can be a real space saver.
I'm not going to try and write a Groovy or Scala tutorial here since there are already so many of those, but my takeaway is that these languages are on the rise, because they offer everything Java has to offer and more (with less code).

Monday, November 2, 2009

Immutable Collections

When we think of immutability in Java, the final keyword should come to mind. It's good practice to finalize whenever possible, particularly when working with multi-threaded applications. The less mutable state that exists, the less chance for side effects and bugs.
Working with collections is a bit trickier. When a class has a getter for a collection, things get a bit more difficult. Let's see what happens.

private final Collection<Object> aCollection;
public MyClass(Collection<Object> coll) {
aCollection = new LinkedList<Object>(coll);
}
public Collection<Object> getCollection() {
return aCollection;
}

Attempting to finalize a collection like this provides very little assurance that the collection will not be mutated. A client that calls getCollection can add or remove from the underlying collection as well as change the elements.
Addressing the first issue of adding or removing from the collection is easy to handle, yet I often see this overlooked. By using the Collections.unmodifiableXXX methods, we can easily create a collection that cannot be added or removed from. The constructor would now look like

public MyClass(Collection<Object> coll) {
aCollection = Collections.unmodifiableCollection(coll);
}

By finalizing in the constructor, this assures that neither private nor public methods can inadvertently mutate the structure of the list. The issue preventing a client from mutating the state of the objects in the list still exists. In order to prevent this, the objects would need to be completely immutable. There's not too much MyClass can do about this.
To sum up, try to make objects immutable whenever possible. You should be defaulting to final objects and unmodifiable collections and removing these restrictions only when absolutely necessary.