Today, I was looking at JDK 8 Collections.max
function declaration and noticed a weird &
in the type declaration. Most normal Java developers will not remember exact function declaration so I am writing it below.
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
The thing that caught my attention was T extends Object & Comparable. I have been doing Java development for last 14 years and I rarely encountered a situation where I had to use & in generics type variables.
After doing some Google research I became aware that these are called intersection types. In my view intersection types are one of the lesser know features on Generics.
The syntax of intersection type is T extends A & B, where T is a type parameter and A and B are two types. This a logical extension of T extends A which means that T can be any type tat implements/extends A. By T extends A & B we are saying our type T should implement/extend both A and B.
Does this explain why max uses <T extends Object & Comparable>? Nope.
By following definition of intersection types, we understand that T is the type that should extend Object class and Comparable interface. But isn’t every Java class extend Object class. So, why we need to specify it explicitly?
The answer is to ensure binary compatibility.
The max
function exist since from the beginning of Collections class. Collections class exist since JDK version 1.2 (released on 8th Dec 1998).
The generics feature was added in JDK 1.5. Before JDK 1.5 (released on 30th Sep 2004), max
function used to return Object
.
As most of you already know, Java implements generics by removing type information in the compiled code. When T extends Comparable, the compiled code will have type of Comparable. This will break binary compatibility as older code expects it to be of type Object
.
Using intersection types, JDK architects were able to overcome this problem. Making the type <T extends Object & Comparable> means that after type information is removed in the compiled code type will be Object. The selected type is always broader of the two types.
Resources to learn more about intersection types
- Intersection Types: Java Generics’ most underused feature – Link