Saturday, 12 June 2010

Generic methods provide type inference

A feature of Java that is powerful yet under-used is type inference. Generic methods provide the ability to infer types at compile time; that is they take the generic typing information from the type that they are assigning to as opposed to the usual inference from a passed instance or explicit declaration.

Let me give you an example from the Collections class:

class Collections {
...

public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}
...

It can be seem that the method emptyList() has a generic type definition, and subsequently provides a generic typed cast of the raw EMPTY_LIST to a list of the generic type. This allows the following usage:

List<string> s = 
     Collections.emptyList();

It can clearly be seen that this construct has no cast, yet satisfies the compiler. So, what is going on? Well the type <T> is being ‘infered’ from the type of list that you are assigning the empty list to, therefore the (List<T> ) cast on the definition of emptyList is automatically providing the correct type for the assignment.

Use with caution! At runtime, type elision removes all type information from the generic definitions so we are effectively back to raw types for everything, and as this is an empty List that is being returned, is type safe. In reality, it is actually a special immutable null implementation of the List<T> interface, to prevent the unwitting developer adding typed items.

This technique can be used in the visitor pattern, to infer type information, and prevent the double dispatch issues.

Don't confuse with the formal type inference that is proposed for Java 7, where the following would be allowed syntax in isolation, and simple allows the lazy programmer to not bother to define the assignment type.


map := new HashMap<string, integer>();

Monday, 31 May 2010

Java Language Pollution

Am I the only one that worries about the mixing of Java language primitives, JVM functionality and API? Perhaps worrying is a bit too strong, but compared with more rigidly structured languages such as C / C++, Java has made a few compromises.
Lets take a look at a few of examples of what I am talking about.:

1) An enum has a base class (note the word ‘class’) definition of

public abstract class Enum< E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable

So is it really is a class, as it extends Object? It is defined using the enum keyword (language primitive) and has lots non class like behaviours, such as being implicitly final, non overridable, and must have the enum elements declared as the first item in the declaration.
Yes it is a class, but one with exceptional behaviour that is enforced on a one off basis - just for enums. The comment in the java docs says it all “This is the common base class of all Java language enumeration types.”
We see Java providing an elegant enum implementation where the enum’s have a lot of the benefits of being a class, but are not entirely class like. 

2) All exceptions in Java must derive from Throwable, but the JVM does not enforce handling of exceptions derived from RuntimeException in the same way as it does for all other Throwable derived classes.
I maintain that throw and catch are language constructs, and should be unaware of the API structure.
Contrast this, with the more abstract C++ where you can throw anything that is relevant to the exception you are processing. Yes you are generally throwing classes, but they do not have to have a specific base class to be properly handles. In many ways C++ has more logical and powerful exception handling, but it requires convention and discipline, rather than compiler enforcement. This can lead to situations where you can fail to catch some category of exception as it went against the convention or leads you to have to catch non specific exceptions using the catch(…) format. This, although is the equivalent of Java’s catch(Throwable t), it does not allow the simple investigation and common reporting of the exception.
So again, we see that Java pragmatically violates the purity language components in the interests of making the language as a whole more useable.

3) References.
The ultimate API / JVM crossover is in the handling of References. SoftReference’s are cleared by the garbage collector in response to memory demand, while WeakReference’s are cleared when there are no soft or hard references. (I would probably be removing PhantomReference’s altogether) It could have been elegantly designed to use a (soft/weak) modifier keyword of the form:

weak Widget w = new Widget();
However, as References are are classes, they can have constructors that can take a reference queue argument.

There is good justification for these examples of language syntax pollution, and it is some of what makes Java a very useable language. I have been writing some C++ recently for the first time in about 3 years, and I had forgotten quite how much easier Java is in comparison. Java allows you to spend a higher percentage of your time writing business logic rather than worrying about getting the constructs right.
Java just kinda works, but it sometimes violates my love of crispness, and makes me feel just a little uncomfortable.

Wednesday, 26 May 2010

Singleton using Enum

Was chatting in the pub last night about singletons, in particular the problems associated with a singleton not being a singleton in the face of serialisation, improper synchronization, reflection and improper subclassing . An interesting solution has presented itself as of java 1.5 in the form of the java enum. Java enums are much more powerful than the equivalents in C++, but much underused as they can take a bit of getting used to.

The enum with a single value effectively gives you the single instance that the rest of the ‘class’ hangs off. It is functionally equivalent to the ‘public static final’ instance, where the instance is in the form of a single enumerated value. You can also provide a static getInstance(), although you can’t then hide access to the enumerated value. It can’t be sub-classed, cant be cloned, and although it can be serialised, de-serialisation can’t create a new instance. It also has the advantage of being able to implement an interface, and this is important to allow isolated unit testing of the consumers of the singleton.

public interface Valueable {

  public int getValue();
  public void setValue(int value);
}

public enum OnlyOneOfMe implements Valueable {

  INSTANCE;

  private int value;

  public static OnlyOneOfMe getInstance() {
    return INSTANCE;
  } 

  public int getValue(){
    return this.value;
  }

  public void setValue(int value){
    this.value = value;
  }
}

public class SingletonTest {

  Valueable onom = OnlyOneOfMe.getInstance();

  @Test    
  public void doTest() {
    onom.setValue(1);
    int value = onom.getValue();  
  }
}

In summary, this technique is powerful because it makes use of language and JVM spec absolute guarantee’s that there will only ever be one of them per JVM. This is not a solution that I have ever seen in real code, but as far as I can see it looks superior to any other singleton solution, provided you don’t want to lazy load.