Skip to content

Java Type Inference: The Diamond Operator

Java's diamond operator lets you cut down on verbosity when writing your code. Learn how it works with generics and type inference, and where it falls short.

You can download the project for this post by clicking HERE.

Intro

The diamond operator is basically syntactic sugar in Java that lets us cut down on verbosity when writing our code. This feature was added in Java 7, so you can only use it in Java 7 or later versions.

It was already available in methods

This syntax was already available in methods; what Java 7 brings us is this same capability for constructors.

If we declared a class GenericMehodClass

public class GenericMehodClass {

    public <T> void printElement(T element){
        System.out.println(element);
    }

}

We can invoke it like this

GenericMehodClass genericMehodClass = new GenericMehodClass();
genericMehodClass.<String>printElement("Hola");
genericMehodClass.<Integer>printElement(5);

But the compiler is smart enough to know that if we pass it a string, we don’t need to tell it again, so we can simply write:

genericMehodClass.printElement("Hola");
genericMehodClass.printElement(5);

Result

Hola 
5 
Hola 
5

Diamond operator

The diamond operator is an improvement in type inference for generics, letting the compiler determine the type of the generic class instead of the developer, saving the effort and time that used to require. Also, as many people thought, there wasn’t much point in having the types duplicated on the right and left sides.

With Java 6

//Java 6 style
List<String> java6List = new ArrayList<String>();

With Java 7

//Java 7 style
List<String> java7List = new ArrayList<>();

This way it’s less verbose: the compiler knows that java7List is going to be of type String because it’s declared on the left side. Both examples do exactly the same thing.

Declaring generic classes

We can use more than just built-in generic classes like List, Map, Set, etc. We can create our own, and make them as complicated as we like. In the following example we’ll see that we can declare a generic class of type U, containing a list of type U and with a constructor of type T

import java.util.ArrayList;
import java.util.List;

public class GenericClass <U> {

    List<U> list = new ArrayList<>();

    <T> GenericClass(T t) throws NoSuchFieldException {
        System.out.println("T: " + t.getClass().getSimpleName());
    }

    public void add(U element){
        list.add(element);
        System.out.println("U: " + list.get(0).getClass().getSimpleName());
    }

}

As we can see, we can instantiate it with the diamond operator:

GenericClass<String> genericClass1 = new GenericClass<>(5);
genericClass1.add("Hola");

If we run it, it will print:

  • T: Integer
  • U: String

Since we said the constructor is going to be Integer, but the class String. However:

GenericClass genericClass2 = new GenericClass("Hola");
genericClass2.add(5);

It tells us the constructor is String, but the class is Integer.

  • T: String
  • U: Integer

The example is contrived; it’s just meant to give you an idea of what you can do with generics when it comes to type inference.

Some restrictions

To benefit from this syntax, you have to use the diamond operator (omitting the type on the right side) whenever the compiler can infer the types from the context. Remember that this is a compiler improvement: it’s now “smarter”, but it’s not a mind reader.

If we go back to the previous example:

With Java 6

//Java 6 style
List<String> java6List = new ArrayList<String>();

With Java 7

//Java 7 style
List<String> java7List = new ArrayList<>();

That would be the correct syntax. If we do this instead

List<String> java7NonDiamondList = new ArrayList();

It will give us a warning

Warning:(26, 43) java: unchecked conversion  required: java.util.List  found: java.util.ArrayList

Because new ArrayList() refers to the raw type of ArrayList and not to its generic type.

Having the flexibility of generic types doesn’t mean we lose Java’s strong typing. For example, in the list we can do

java7List.add("Hola");

But we can’t do (in the same list)

java7List.add(5);

Because it gives us the following error:

add (java.lang.String) in List cannot be applied to (int)

References

“Java Type Inference: The Diamond Operator” by Dionisio Cortés at jarroba.com, licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0. Registered at Safe Creative.

Dionisio Cortés

Systems engineer and software engineering graduate. Some say I am a Java developer in decline, others a Pythonista on the rise; either way, I enjoy programming and tinkering with any language and technology.

You may also like

Comments

Leave a comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.