Tuesday, April 15, 2008

Java Type Inference Sucks

Why doesn't this work?! Boo Java.
Variable unpacked_var =
(this_copy.unpackedVar == other.unpackedVar ?
this_copy.unpackedVar :
throw new IllegalStateException("Unhandled casee"));


  1. Is throw a statement or an expression? Does Java have an injection from statements into expressions like C does? Does the ternary operator accept statements?

    I wasn't aware that Java had any type inference. That's why you have to write out the full types of all your variable.

  2. Okay, you're right. This blog post requires way more explanation than I gave.

    You are absolutely right, throw is a statement and not an expression. The weird thing was that Eclipse was giving me a type error rather than a syntax error for the example above, which temporarily made me think it was an expression. Frankly, I don't see any reason why it shouldn't be an expression, but whatever.

    Re type inference, well something like this wouldn't be considered type inference in any sophisticated fashion, but as far as 'determining the type of an expression from its sub-expressions' is type inference, then this qualifies.

    Java DOES have a much more interesting form of 'type inference,' however, since Java5. A perfect example is the emptyList() method in the java.util.Collections class. emptyList() returns an immutable, empty list. The method signature is:

    public static final List emptyList()

    However, if I want to use this method, most of the time I do not have to explicitly parameterize the method, although it is legal:

    List = Collections.emptyList();

    Java is required to figure out the parameterization based on the type it is being assigned to, so I can say:

    List = Collections.emptyList();

    And Java knows what I mean. For this reason, static factory methods are way more convenient for parameterized classes than regular constructors, where the above rule does not apply. This is a far cry from Hinley-Millner type inference, but in the Java world it's more than we've come to expect.

  3. Boo, livejournal ate my generics. This is what those three lines should have said:

    public static final < T > List< T > emptyList()

    List< Integer > _list = Collections.< Integer >emptyList();

    List< Integer > _list = Collections.emptyList();