Declaring the base builder as VehicleBuilder<T extends VehicleBuilder<T>> lets its inherited color() method return the actual subclass type instead of the base type, so a chain can call a subclass-only method like doors() right after it. Without the self-type, color() would return the base type and doors() would not compile.
class VehicleBuilder<T extends VehicleBuilder<T>> {
protected String color = "black";
@SuppressWarnings("unchecked")
T color(String c) { color = c; return (T) this; }
}
class CarBuilder extends VehicleBuilder<CarBuilder> {
private int doors = 4;
CarBuilder doors(int d) { doors = d; return this; }
String build() { return "Car: " + color + ", " + doors + " doors"; }
}
CarBuilder builder = new CarBuilder().color("red").doors(2);
System.out.println(builder.build());
Car: red, 2 doors
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-09-27