HuntExams Academy logo
JavaBeginner#generics

What is the diamond operator in generics?

Answer

Introduced in Java 7, it lets you omit the explicit type argument on the right-hand side of a generic instantiation, since the compiler infers it from the declared variable type.

Example

List<Map<String, Integer>> list = new ArrayList<>(); // <> infers Map<String,Integer>

Detailed explanation

The diamond operator, written as <>, is a Java feature introduced in Java 7 that lets you omit explicit type arguments when creating an instance of a generic class. Instead of repeating a type on both sides of an assignment, you let the compiler infer the constructor expression's type arguments. For example, List<Map<String, Integer>> list = new ArrayList<>(); creates an ArrayList whose elements are maps from String to Integer. Here, the compiler infers Map<String, Integer> as the type argument for ArrayList, while the variable is declared using the List interface.

Before Java 7, you would normally write List<Map<String, Integer>> list = new ArrayList<Map<String, Integer>>();. The diamond form removes this repetition without weakening compile-time type checking. It is particularly useful with nested generic types, where repeated declarations become difficult to read and maintain. Both versions allow compatible maps to be added and reject incompatible elements, such as a String. The diamond does not change the object into a different collection implementation: the actual object is still an ArrayList.

Under the hood, the compiler performs type inference by considering available information, including constructor arguments and the target type supplied by the surrounding context. Therefore, inference is not limited to the declared variable type. For example, new ArrayList<>(existingStrings), where existingStrings is a List<String>, can use the constructor argument to infer String. This is a compile-time process, not runtime discovery of the values stored in the collection. Java generally implements generics through type erasure, so using diamond adds no separate runtime inference mechanism or overhead.

In interviews, distinguish diamond syntax from raw types and from var. new ArrayList<>() participates in generic type inference, whereas new ArrayList() uses a raw type and can introduce unchecked warnings and reduced type safety. Diamond belongs to class instance creation expressions, not declarations such as List<> list. Also, var, introduced in Java 10, infers a local variable's type rather than merely omitting constructor type arguments. A strong answer states the Java version, demonstrates the shorter syntax, and explains that inference preserves generic type checking.

Key points to remember

  • Introduced in Java 7, <> omits explicit type arguments when instantiating a generic class.
  • In new ArrayList<>(), the compiler infers ArrayList's element type.
  • Inference can use the target type, constructor arguments, and surrounding context.
  • Diamond preserves compile-time generic type checking and is not a raw type.
  • Diamond performs no runtime type inference and is different from Java 10's var.

Common mistakes candidates make

  • Saying the type arguments are inferred at runtime from elements added to the collection.
  • Treating new ArrayList<>() and the raw expression new ArrayList() as equivalent.
  • Using diamond in a variable declaration, such as List<> list, instead of in an instance creation expression.

Likely follow-up questions

What happens with var list = new ArrayList<>()?

The inferred variable type is ArrayList<Object>, because there is no explicit target element type or constructor argument to constrain it further. To obtain ArrayList<String>, write var list = new ArrayList<String>();.

Can the diamond operator be used with anonymous classes?

Java 7 and Java 8 do not allow diamond with anonymous class creation. Java 9 added support, subject to restrictions on inferred types and methods declared in the anonymous class.

Does diamond make List<Integer> assignable to List<Number>?

No; generic types remain invariant, so List<Integer> is not a subtype of List<Number>. A List<? extends Number> reference can refer to a List<Integer>, but you cannot add arbitrary Number values through that reference.

Interview tip: Start with Java 7 and the purpose of <>, show the provided example, and finish by distinguishing compile-time inference from raw types.

Related Interview Questions

1
JavaBeginner#exceptions

What is the exception hierarchy in Java?

Open
2
JavaBeginner#exceptions

What is a custom exception and how do you create one?

Open
3
JavaIntermediate#exceptions

What is exception chaining (cause)?

Open