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.

You may also like
Advanced Dockerfile: Multi-Stage Builds, Registries, and Tricks
Free Docker course. Expert Docker tricks: multi-stage builds, optimizing images, faster build times, and distributing images through Docker registries.
Dockerfile: Directives and Dockerizing Projects
Free Docker course. A Dockerfile is a file of directives for building and deploying custom applications with Docker. Learn how to Dockerize your projects.



Leave a comment