skip to content

Type Parameter Conventions and Diamond

The T, E, K, V and N naming conventions, multiple parameters, and the diamond operator that lets the compiler infer arguments at instantiation. Small, but it is the vocabulary every generic signature is written in.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

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

open as a page

What are the conventional single-letter names for Java generic type parameters (T, E, K, V, N), and why do these conventions matter?

level: juniorimportance: should knowfreq 55%

basics

~20 s

They are agreed-on short names for generic type parameters: T means a general Type, E an Element (collections), K a Key and V a Value (maps), N a Number. They are just naming conventions that make code easier to read.

open as a page

How do you declare a generic class or method with multiple type parameters, and how are they bound to actual types?

level: middleimportance: should knowfreq 50%

basics

~10 s

Put several comma-separated placeholders in the angle brackets, like class Pair<K,V> or <T,R> R map(T in). Each placeholder is filled independently when you use the class or call the method, e.g. Pair<String,Integer>.

open as a page

When should you introduce a type parameter on a method (a generic method) rather than on the whole class, and how does inference make it ergonomic?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Use a generic method when only one method needs the placeholder type and the class itself doesn't store it. Declare the type parameter before the return type, and callers usually don't have to pass it because the compiler infers it from the arguments.

open as a page

Why couldn't the diamond operator originally be used with anonymous classes, and what changed in Java 9?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

In Java 7-8 you couldn't write the diamond <> when creating an anonymous class, because the compiler couldn't always name the inferred type for the hidden subclass it generates. Java 9 relaxed this: it now allows <> with anonymous classes whenever the inferred type can be expressed.

open as a page