skip to content

What is the diamond operator (<>) introduced in Java 7, and how does it work?

level: juniorimportance: must knowfreq 70%

answer

  1. <> = empty angle brackets, looks like a diamond
  2. Java 7; infers type args from the target type
  3. new ArrayList<>() (safe) vs new ArrayList() (raw, unsafe)
  4. Works from variable type, return type, method arg
  5. With var it infers Object — specify explicitly

basics

~20 s

The diamond operator is the empty angle brackets <> used on the right side of an assignment. It tells the compiler to infer the generic type arguments from the left side, so you don't repeat them. Example: List<String> list = new ArrayList<>();

solid answer

~50 s

The diamond operator, `<>`, was added in Java 7 to reduce boilerplate in generic instantiation. Before it, you had to repeat the full type arguments on both sides: `Map<String, List<Integer>> m = new HashMap<String, List<Integer>>();`. With the diamond you write `new HashMap<>()` and the compiler infers the type arguments from the target type (the variable's declared type, a method return type, or an argument's expected type). It's called the diamond because `<>` looks like one. Crucially, `new ArrayList<>()` is different from `new ArrayList()`: the diamond produces a properly parameterized type via inference, whereas omitting the brackets entirely creates a raw type, which loses type safety and generates unchecked warnings. Inference works from any target-typing context, including return statements and method arguments. In Java 7-8 it could not be used with anonymous classes; Java 9 lifted that restriction.

code

java · 11 lines
java
// Verbose pre-Java 7
Map<String, List<Integer>> m1 = new HashMap<String, List<Integer>>();

// Java 7+ diamond: type args inferred from the left-hand type
Map<String, List<Integer>> m2 = new HashMap<>();

// Inference also works from method return type and arguments
List<String> make() { return new ArrayList<>(); }

// NOT the diamond — this is a RAW type (unsafe, unchecked warning)
List<String> bad = new ArrayList();

go deeper

for a junior

Knows to write new ArrayList<>() and that <> means 'infer the type arguments.'

for a middle

Distinguishes diamond from raw type, knows it works from any target-typing context and infers Object under var.

for a senior

Explains the underlying target-type inference, its limits, and the safety implications versus raw types.

for a principal

Can reason about inference corner cases (var, nested generics, overload resolution) and guide codebase-wide avoidance of raw types.

## The problem the diamond solves Before Java 7, generic instantiation forced you to repeat the type arguments on both sides of the assignment: ```java // Java 5/6 — verbose Map<String, List<Integer>> m = new HashMap<String, List<Integer>>(); ``` The right-hand side's type arguments are redundant — the compiler already knows them from the left-hand declared type. The **diamond operator** `<>` (Java 7) lets you omit them: ```java // Java 7+ Map<String, List<Integer>> m = new HashMap<>(); ``` It is called the 'diamond' because the empty angle brackets `<>` look like a diamond shape. ## How it works: type inference from a target When you write `new HashMap<>()`, the compiler performs **type inference**: it looks at the **target type** — the context that the expression is being used in — and fills in the type arguments. Target-typing contexts include: - A variable's declared type: `List<String> xs = new ArrayList<>();` - A method's declared return type: `return new ArrayList<>();` - A method parameter's expected type: `process(new ArrayList<>());` In each case the compiler reads what type is expected and infers the arguments for the diamond. ## Diamond vs raw type — a critical distinction These three are NOT the same: ```java List<String> a = new ArrayList<String>(); // explicit — fine List<String> b = new ArrayList<>(); // diamond — inferred, fine List<String> c = new ArrayList(); // RAW type — compiles with a warning, unsafe ``` - `new ArrayList<>()` is a **parameterized** type; the compiler infers `String` and keeps full type safety. - `new ArrayList()` (no brackets) is a **raw type**. It opts out of generics, produces 'unchecked' warnings, and lets bad values slip in. Raw types exist only for backward compatibility with pre-generics code — avoid them. So the diamond is the safe shorthand; dropping the brackets entirely is the unsafe legacy form. ## Where inference can fail The diamond needs enough context to infer. If there's no clear target type, inference can default to something too wide. For example: ```java var list = new ArrayList<>(); // infers ArrayList<Object> — probably not what you want ``` With `var` (Java 10+), there's no declared type to infer from, so the diamond falls back to `Object`. In that case you should write the type argument explicitly: `var list = new ArrayList<String>();`. ## History and the anonymous-class restriction Java 7 introduced the diamond but **forbade it on anonymous inner classes**. Java 9 lifted that restriction (covered separately). The general rule today: prefer the diamond for all ordinary generic instantiations. ## Why it matters The diamond removes redundancy, making generic-heavy code far more readable, while preserving the compile-time type safety that raw types throw away. It is one of the most-used everyday generics features.

  • Is `new ArrayList<>()` the same as `new ArrayList()`?
    No. `<>` triggers inference and yields a parameterized, type-safe ArrayList. Omitting the brackets creates a raw type, which disables generic checks and produces unchecked warnings.
  • What does the diamond infer if you use it with `var`?
    It infers Object, because var has no declared target type to infer from. e.g. `var l = new ArrayList<>()` is ArrayList<Object>; specify the argument explicitly instead.

saying these in an interview costs you the question

  • Confusing the diamond new ArrayList<>() with the raw type new ArrayList()
  • Thinking the diamond works without any target-typing context
  • Believing it changes runtime behavior (it's pure compile-time inference)
  • Forgetting that with var the diamond falls back to Object

context