Skip to main content

Diamond at the gate

Posted by forax on August 27, 2009 at 6:22 AM PDT

Maurizio Cimadamore has just push a patch that enable to use diamond syntax to instantiate a generics.


The diamond syntax is one of the changes introduced by the
coin project and
is the first one introduced in jdk7 repository.

The diamond syntax allows to instantiate a generic type without specify the
type argument, the compiler will infer them using the context.
In the example above, you can note that the list or the map
are instantiated without providing things between the brackets.
This change doesn't turn Java into something really different but,
in my opinion, it really improves the readability.

Just one line about the algorithm used, the constructor inference syntax
uses it own algorithm instead of relying on the one used to infer
method type argument.
I think this is not a good idea
because we have now two different
inference algorithms but Maurizio thinks that this new algorithm better fit
with the constructor inference problem and he is more expert than me :)

  import java.util.*;

  public class DiamondTest {
      public static void main(String[] args) {
          List<String> list = new ArrayList<>();
          Collections.addAll(list, args);

          Map<Integer, List<String>> map = new HashMap<>();
          for(String s:list) {
              int length = s.length();
              List<String> l = map.get(length);
              if (l == null) {
                  l = new ArrayList<>();
                  map.put(length, l);
              }
              l.add(s);
          }
          System.out.println(map);
      }
  }

If, like me, you can't wait the next binary build.
I have prepared a jar tools-diamond.jar containing javac
compiled with the diamond patch. It requires a recent jdk7 beta.

To compile :

  /usr/jdk/jdk1.7.0/bin/java -cp tools-diamond.jar:. com.sun.tools.javac.Main DiamondTest.java

And to execute :

$ /usr/jdk/jdk1.7.0/bin/java DiamondTest foo bar foobar
{3=[foo, bar], 6=[foobar]}

Cheers,

Rémi

Related Topics >>

Comments

Better, but only just. Why

Better, but only just.

Why on earth not just support C++ style constructor invocation? No right-hand side is required.

HashMap<String, List<String>> map();
Foo foo(map);


Declaring a variable using a supertype or interface rather than the actual instantiated type is very rarely a good idea (if its a TreeMap, say that it's a TreeMap - the golden rule of code readability is to always say what you mean).

In the exceptional case that a variable has to be declared as the supertype/interface, just use the existing syntax.

Java object aren't stack allocated

Because in C++:

HashMap&lt;String, List&lt;String&gt;&gt; map();

is stack allocated and not heap allocated like in Java.

BTW, this line doesn't work in C++ because the C++ parser read '>>' as
a right shift :)

Rémi

Any reason to keep the <>

Any reason to keep the <> after "new ArrayList" at all? The compiler might know if it is a genericable class already.

Re: Any reason to keep the <>

The reason is backward compatibility.
ArrayList (without angle brackets) can't act as a ArrayList<> because
you can add anything to an ArrayList to be compatible with pre 1.5 code.

Rémi

Hmmm ... I don't get it. Lets

Hmmm ... I don't get it. Lets simplify things to: List list = new ArrayList<>(); In this case, from the point of view of the developer only the "List" is the interesting part, as, without casting you'll work just with the List interfaces which has been typed to "String". The left side of the expression is meaningless for further type checking. So, I thought, the compiler should look if the variable the instance gets assigned to has type information just use them also for the used implementation. List list = new ArrayList(); would be enough then. Is this example to simple? What is it I overlook?

Nice to have

That will be nice to have. Although it's interesting to note the inference difference between Java and C#. // Java List list = new ArrayList<>(); // C# var list = new ArrayList(); I rather like the C# inference as you can compose with it (types flows out-worth rather than in-worth), making it more than just boiler-plate reduction.

I don't like the C# var

I don't like the C# var keyword, I think it's dangerous. Knowing what type is really used when reading the code is important I think. But why no just having to type: List list = new ArrayList() rather than: List list = new ArrayList<>()

More than just boiler plate reduction

The var keyword does more than just aid in reduction of boiler code. I don't really think it makes code less readable in practice, although it can obviously be abused just like anything else in a programming language. Where it shines is in composability, the ability to new up stuff and let the type flow through. Scala, JavaFX etc. also does this and I expect we'll see a lot of type inference and dynamic types in the future.