Generics
Generics
Type-Safe Containers
Your Box class stores an Object. When you get it out, you cast to String - but
what if someone put an Integer in? Generics let you say Box<String> - the
compiler ensures only Strings go in, no casting needed.
Generic class
Define a class with a type parameter.
public class GenericClass {
static class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
public boolean hasValue() {
return value != null;
}
}
public static void main(String[] args) {
System.out.println("Generic class:\n");
// Box for Integer
Box<Integer> intBox = new Box<>();
intBox.set(42);
System.out.println(" Integer box: " + intBox.get());
// Box for String
Box<String> strBox = new Box<>();
strBox.set("Hello");
System.out.println(" String box: " + strBox.get());
// Box for Double
Box<Double> doubleBox = new Box<>();
doubleBox.set(3.14);
System.out.println(" Double box: " + doubleBox.get());
// T is a type parameter (placeholder for actual type)
// Specified at instantiation: Box<Integer>
// Provides compile-time type safety
// No casting needed when retrieving value
System.out.println("\nType safety:");
Box<String> box = new Box<>();
box.set("Text");
// box.set(123); // Compile error - type mismatch
String value = box.get(); // No cast needed
System.out.println(" Value: " + value);
System.out.println("\nWithout generics (old way):");
class ObjectBox {
private Object value;
public void set(Object value) {
this.value = value;
}
public Object get() {
return value;
}
}
ObjectBox oldBox = new ObjectBox();
oldBox.set("Text");
String str = (String) oldBox.get(); // Cast required
System.out.println(" Value: " + str);
// Runtime error possible:
oldBox.set(123);
// String wrong = (String) oldBox.get(); // ClassCastException at runtime
System.out.println("\nMultiple type uses:");
Box<Integer> scores = new Box<>();
scores.set(95);
Box<String> name = new Box<>();
name.set("Alice");
Box<Boolean> active = new Box<>();
active.set(true);
System.out.println(" Score: " + scores.get());
System.out.println(" Name: " + name.get());
System.out.println(" Active: " + active.get());
}
}
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Generic class:\n");outputGeneric class: Generic class:this.value ← 42
pass 1 of 75public void set(T value42) {6 this.value→ 42 = value42;7}All 7 passes — pass 1 is the card above pass valuethis.value1 42 42 2 Hello Hello 3 3.14 3.14 4 Text Text 5 95 95 6 Alice Alice 7 true true System.out.println(" Integer box: " + intBox.get());
23intBox.set(42);24System.out.println(" Integer box: " + intBox.get());public T get()
pass 1 of 109public T get() {10 return value42;11}All 10 passes — pass 1 is the card above pass value1 42 2 42 3 Hello 4 Hello 5 3.14 6 3.14 7 Text 8 95 9 Alice 10 true System.out.println(" Integer box: " + intBox.get());
23intBox.set(42);24System.out.println(" Integer box: " + intBox.get());output Integer box: 42System.out.println(" Integer box: " + intBox.get());
23intBox.set(42);24System.out.println(" Integer box: " + intBox.get());output Integer box: 42System.out.println(" String box: " + strBox.get());
28strBox.set("Hello");29System.out.println(" String box: " + strBox.get());System.out.println(" String box: " + strBox.get());
28strBox.set("Hello");29System.out.println(" String box: " + strBox.get());output String box: HelloSystem.out.println(" String box: " + strBox.get());
28strBox.set("Hello");29System.out.println(" String box: " + strBox.get());output String box: HelloSystem.out.println(" Double box: " + doubleBox.get());
33doubleBox.set(3.14);34System.out.println(" Double box: " + doubleBox.get());System.out.println(" Double box: " + doubleBox.get());
33doubleBox.set(3.14);34System.out.println(" Double box: " + doubleBox.get());output Double box: 3.14System.out.println(" Double box: " + doubleBox.get());
33doubleBox.set(3.14);34System.out.println(" Double box: " + doubleBox.get());3536// T is a type parameter (placeholder for actual type)37// Specified at instantiation: Box<Integer>38// Provides compile-time type safety39// No casting needed when retrieving value4041System.out.println("\nType safety:");output Double box: 3.14 Type safety: Type safety:System.out.println(" Value: " + value);
47String value = box.get(); // No cast needed48System.out.println(" Value: " + valueText);4950System.out.println("\nWithout generics (old way):");5152class ObjectBox {53 private Object value;54 55 public void set(Object value) {56 this.value = value;57 }58 59 public Object get() {60 return value;61 }62}6364ObjectBox oldBox = new ObjectBox();65oldBox.set("Text");66String str = (String) oldBox.get(); // Cast requiredoutput Value: Text Value: Text Without generics (old way): Without generics (old way):this.value ← Text
pass 1 of 255public void set(Object valueText) {56 this.value→ Text = valueText;57}oldBox.set("Text");
64ObjectBox oldBox = new ObjectBox();65oldBox.set("Text");66String str = (String) oldBox.get(); // Cast required67System.out.println(" Value: " + str);public Object get()
59public Object get() {60 return valueText;61}str ← Text
65oldBox.set("Text");66String str→ Text = (String) oldBox.get(); // Cast required67System.out.println(" Value: " + strText);6869// Runtime error possible:70oldBox.set(123);71// String wrong = (String) oldBox.get(); // ClassCastException at runtimeoutput Value: Textthis.value ← 123
pass 2 of 255public void set(Object value123) {56 this.value→ 123 = value123;57}scores ← ⟨GenericClass$Box A⟩
69// Runtime error possible:70oldBox.set(123);71// String wrong = (String) oldBox.get(); // ClassCastException at runtime7273System.out.println("\nMultiple type uses:");7475Box<Integer> scores→ ⟨GenericClass$Box A⟩ = new Box<>();76scores.set(95);output Multiple type uses:name ← ⟨GenericClass$Box B⟩
75Box<Integer> scores = new Box<>();76scores.set(95);7778Box<String> name→ ⟨GenericClass$Box B⟩ = new Box<>();79name.set("Alice");active ← ⟨GenericClass$Box C⟩
78Box<String> name = new Box<>();79name.set("Alice");8081Box<Boolean> active→ ⟨GenericClass$Box C⟩ = new Box<>();82active.set(true);active.set(true);
81Box<Boolean> active = new Box<>();82active.set(true);8384System.out.println(" Score: " + scores.get());85System.out.println(" Name: " + name.get());System.out.println(" Score: " + scores.get());
84System.out.println(" Score: " + scores.get());85System.out.println(" Name: " + name.get());86System.out.println(" Active: " + active.get());output Score: 95System.out.println(" Name: " + name.get());
84 System.out.println(" Score: " + scores.get());85 System.out.println(" Name: " + name.get());86 System.out.println(" Active: " + active.get());87}output Name: AliceSystem.out.println(" Active: " + active.get());
85 System.out.println(" Name: " + name.get());86 System.out.println(" Active: " + active.get());87}output Active: true
class Box<T> - T is a placeholder for any type. Specified when used.
Generic with methods
Methods using the type parameter.
public class GenericWithMethods {
static class Container<T> {
private T item;
public void store(T item) {
this.item = item;
System.out.println(" Stored: " + item);
}
public T retrieve() {
System.out.println(" Retrieved: " + item);
return item;
}
public boolean isEmpty() {
return item == null;
}
public void clear() {
item = null;
System.out.println(" Cleared");
}
public String getInfo() {
if (item == null) {
return "Empty container";
}
return "Container holding: " + item.getClass().getSimpleName();
}
}
public static void main(String[] args) {
System.out.println("Generic methods:\n");
Container<String> strContainer = new Container<>();
strContainer.store("Hello");
String value = strContainer.retrieve();
System.out.println(" Info: " + strContainer.getInfo());
// Methods in generic class can use type parameter T
// Parameters and return types can be T
// Type is consistent throughout the instance
System.out.println("\nInteger container:");
Container<Integer> intContainer = new Container<>();
System.out.println(" Empty: " + intContainer.isEmpty());
intContainer.store(42);
System.out.println(" Empty: " + intContainer.isEmpty());
int num = intContainer.retrieve();
System.out.println(" Value: " + num);
System.out.println("\nPair class:");
class Pair<T> {
private T first;
private T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
public void swap() {
T temp = first;
first = second;
second = temp;
}
public void display() {
System.out.println(" First: " + first + ", Second: " + second);
}
}
Pair<String> namePair = new Pair<>("Alice", "Bob");
namePair.display();
namePair.swap();
System.out.println(" After swap:");
namePair.display();
System.out.println("\nPoint class:");
class Point<T extends Number> {
private T x;
private T y;
public Point(T x, T y) {
this.x = x;
this.y = y;
}
public T getX() { return x; }
public T getY() { return y; }
public double distance() {
double dx = x.doubleValue();
double dy = y.doubleValue();
return Math.sqrt(dx * dx + dy * dy);
}
public void display() {
System.out.println(" Point(" + x + ", " + y + ")");
}
}
int pointX = 3;
Point<Integer> intPoint = new Point<>(pointX, 4);
intPoint.display();
System.out.println(" Distance: " + intPoint.distance());
Point<Double> doublePoint = new Point<>(1.5, 2.5);
doublePoint.display();
System.out.println(" Distance: " + doublePoint.distance());
}
}
public class GenericWithMethods {
static class Container<T> {
private T item;
public void store(T item) {
this.item = item;
System.out.println(" Stored: " + item);
}
public T retrieve() {
System.out.println(" Retrieved: " + item);
return item;
}
public boolean isEmpty() {
return item == null;
}
public void clear() {
item = null;
System.out.println(" Cleared");
}
public String getInfo() {
if (item == null) {
return "Empty container";
}
return "Container holding: " + item.getClass().getSimpleName();
}
}
public static void main(String[] args) {
System.out.println("Generic methods:\n");
Container<String> strContainer = new Container<>();
strContainer.store("Hello");
String value = strContainer.retrieve();
System.out.println(" Info: " + strContainer.getInfo());
// Methods in generic class can use type parameter T
// Parameters and return types can be T
// Type is consistent throughout the instance
System.out.println("\nInteger container:");
Container<Integer> intContainer = new Container<>();
System.out.println(" Empty: " + intContainer.isEmpty());
intContainer.store(42);
System.out.println(" Empty: " + intContainer.isEmpty());
int num = intContainer.retrieve();
System.out.println(" Value: " + num);
System.out.println("\nPair class:");
class Pair<T> {
private T first;
private T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
public void swap() {
T temp = first;
first = second;
second = temp;
}
public void display() {
System.out.println(" First: " + first + ", Second: " + second);
}
}
Pair<String> namePair = new Pair<>("Alice", "Bob");
namePair.display();
namePair.swap();
System.out.println(" After swap:");
namePair.display();
System.out.println("\nPoint class:");
class Point<T extends Number> {
private T x;
private T y;
public Point(T x, T y) {
this.x = x;
this.y = y;
}
public T getX() { return x; }
public T getY() { return y; }
public double distance() {
double dx = x.doubleValue();
double dy = y.doubleValue();
return Math.sqrt(dx * dx + dy * dy);
}
public void display() {
System.out.println(" Point(" + x + ", " + y + ")");
}
}
int pointX = 5;
Point<Integer> intPoint = new Point<>(pointX, 4);
intPoint.display();
System.out.println(" Distance: " + intPoint.distance());
Point<Double> doublePoint = new Point<>(1.5, 2.5);
doublePoint.display();
System.out.println(" Distance: " + doublePoint.distance());
}
}
public class GenericWithMethods {
static class Container<T> {
private T item;
public void store(T item) {
this.item = item;
System.out.println(" Stored: " + item);
}
public T retrieve() {
System.out.println(" Retrieved: " + item);
return item;
}
public boolean isEmpty() {
return item == null;
}
public void clear() {
item = null;
System.out.println(" Cleared");
}
public String getInfo() {
if (item == null) {
return "Empty container";
}
return "Container holding: " + item.getClass().getSimpleName();
}
}
public static void main(String[] args) {
System.out.println("Generic methods:\n");
Container<String> strContainer = new Container<>();
strContainer.store("Hello");
String value = strContainer.retrieve();
System.out.println(" Info: " + strContainer.getInfo());
// Methods in generic class can use type parameter T
// Parameters and return types can be T
// Type is consistent throughout the instance
System.out.println("\nInteger container:");
Container<Integer> intContainer = new Container<>();
System.out.println(" Empty: " + intContainer.isEmpty());
intContainer.store(42);
System.out.println(" Empty: " + intContainer.isEmpty());
int num = intContainer.retrieve();
System.out.println(" Value: " + num);
System.out.println("\nPair class:");
class Pair<T> {
private T first;
private T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
public void swap() {
T temp = first;
first = second;
second = temp;
}
public void display() {
System.out.println(" First: " + first + ", Second: " + second);
}
}
Pair<String> namePair = new Pair<>("Alice", "Bob");
namePair.display();
namePair.swap();
System.out.println(" After swap:");
namePair.display();
System.out.println("\nPoint class:");
class Point<T extends Number> {
private T x;
private T y;
public Point(T x, T y) {
this.x = x;
this.y = y;
}
public T getX() { return x; }
public T getY() { return y; }
public double distance() {
double dx = x.doubleValue();
double dy = y.doubleValue();
return Math.sqrt(dx * dx + dy * dy);
}
public void display() {
System.out.println(" Point(" + x + ", " + y + ")");
}
}
int pointX = 6;
Point<Integer> intPoint = new Point<>(pointX, 4);
intPoint.display();
System.out.println(" Distance: " + intPoint.distance());
Point<Double> doublePoint = new Point<>(1.5, 2.5);
doublePoint.display();
System.out.println(" Distance: " + doublePoint.distance());
}
}
public static void main(String[] args)
32public static void main(String[] args) {33 System.out.println("Generic methods:\n");outputGeneric methods: Generic methods:this.item ← Hello
pass 1 of 25public void store(T itemHello) {6 this.item→ Hello = itemHello;7 System.out.println(" Stored: " + itemHello);8}output Stored: Hellopublic T retrieve()
pass 1 of 210public T retrieve() {11 System.out.println(" Retrieved: " + itemHello);12 return itemHello;13}output Retrieved: HelloSystem.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());System.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());output Info: Container holding: StringSystem.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());3940// Methods in generic class can use type parameter T41// Parameters and return types can be T42// Type is consistent throughout the instance4344System.out.println("\nInteger container:");4546Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Info: Container holding: String Integer container: Integer container:public boolean isEmpty()
pass 1 of 415public boolean isEmpty() {16 return itemnull == null;17}All 4 passes — pass 1 is the card above pass item1 null 2 null 3 42 4 42 System.out.println(" Empty: " + intContainer.isEmpty());
46Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Empty: trueSystem.out.println(" Empty: " + intContainer.isEmpty());
46Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Empty: truethis.item ← 42
pass 2 of 25public void store(T item42) {6 this.item→ 42 = item42;7 System.out.println(" Stored: " + item42);8}output Stored: 42System.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();System.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();output Empty: falseSystem.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();output Empty: falsepublic T retrieve()
pass 2 of 210public T retrieve() {11 System.out.println(" Retrieved: " + item42);12 return item42;13}output Retrieved: 42System.out.println(" Value: " + num);
50int num = intContainer.retrieve();51System.out.println(" Value: " + num42);5253System.out.println("\nPair class:");output Value: 42 Value: 42 Pair class: Pair class:this.first ← Alice, this.second ← Bob
59public Pair(T firstAlice, T secondBob) {60 this.first→ Alice = firstAlice;61 this.second→ Bob = secondBob;62}public void display()
pass 1 of 278public void display() {79 System.out.println(" First: " + firstAlice + ", Second: " + secondBob);80}output First: Alice, Second: Bobtemp ← Alice, first ← Bob, second ← Alice
72public void swap() {73 T temp→ Alice = first;74 first→ Bob = secondBob;75 second→ Alice = tempAlice;76}System.out.println(" After swap:");
85namePair.swap();86System.out.println(" After swap:");87namePair.display();output After swap: After swap:public void display()
pass 2 of 278public void display() {79 System.out.println(" First: " + firstBob + ", Second: " + secondAlice);80}output First: Bob, Second: AliceSystem.out.println(" Point class:");
89System.out.println("\nPoint class:");9091class Point<T extends Number> {92 private T x;93 private T y;94 95 public Point(T x, T y) {96 this.x = x;97 this.y = y;98 }99 100 public T getX() { return x; }101 public T getY() { return y; }102 103 public double distance() {104 double dx = x.doubleValue();105 double dy = y.doubleValue();106 return Math.sqrt(dx * dx + dy * dy);107 }108 109 public void display() {110 System.out.println(" Point(" + x + ", " + y + ")");111 }112}113114int pointX = 3; //@pointX=3, 5, 6115Point<Integer> intPoint = new Point<>(pointX, 4);116intPoint.display();output Point class: Point class:this.x ← 3, this.y ← 4
pass 1 of 295public Point(T x3, T y4) {96 this.x→ 3 = x3;97 this.y→ 4 = y4;98}intPoint ← ⟨GenericWithMethods$1Point A⟩
114int pointX = 3; //@pointX=3, 5, 6115Point<Integer> intPoint→ ⟨GenericWithMethods$1Point A⟩ = new Point<>(pointX, 4);116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());public void display()
pass 1 of 2109public void display() {110 System.out.println(" Point(" + x3 + ", " + y4 + ")");111}output Point(3, 4)intPoint.display();
115Point<Integer> intPoint = new Point<>(pointX, 4);116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());dx ← 3.0, dy ← 4.0
pass 1 of 2103public double distance() {104 double dx→ 3.0 = x.doubleValue();105 double dy→ 4.0 = y.doubleValue();106 return Math.sqrt(dx3.0 * dx + dy4.0 * dy);107}System.out.println(" Distance: " + intPoint.distance());
116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());118119Point<Double> doublePoint = new Point<>(1.5, 2.5);120doublePoint.display();output Distance: 5.0this.x ← 1.5, this.y ← 2.5
pass 2 of 295public Point(T x1.5, T y2.5) {96 this.x→ 1.5 = x1.5;97 this.y→ 2.5 = y2.5;98}doublePoint ← ⟨GenericWithMethods$1Point B⟩
119Point<Double> doublePoint→ ⟨GenericWithMethods$1Point B⟩ = new Point<>(1.5, 2.5);120doublePoint.display();121System.out.println(" Distance: " + doublePoint.distance());public void display()
pass 2 of 2109public void display() {110 System.out.println(" Point(" + x1.5 + ", " + y2.5 + ")");111}output Point(1.5, 2.5)doublePoint.display();
119 Point<Double> doublePoint = new Point<>(1.5, 2.5);120 doublePoint.display();121 System.out.println(" Distance: " + doublePoint.distance());122}dx ← 1.5, dy ← 2.5
pass 2 of 2103public double distance() {104 double dx→ 1.5 = x.doubleValue();105 double dy→ 2.5 = y.doubleValue();106 return Math.sqrt(dx1.5 * dx + dy2.5 * dy);107}System.out.println(" Distance: " + doublePoint.distance());
120 doublePoint.display();121 System.out.println(" Distance: " + doublePoint.distance());122}output Distance: 2.9154759474226504
public static void main(String[] args)
32public static void main(String[] args) {33 System.out.println("Generic methods:\n");outputGeneric methods: Generic methods:this.item ← Hello
pass 1 of 25public void store(T itemHello) {6 this.item→ Hello = itemHello;7 System.out.println(" Stored: " + itemHello);8}output Stored: Hellopublic T retrieve()
pass 1 of 210public T retrieve() {11 System.out.println(" Retrieved: " + itemHello);12 return itemHello;13}output Retrieved: HelloSystem.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());System.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());output Info: Container holding: StringSystem.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());3940// Methods in generic class can use type parameter T41// Parameters and return types can be T42// Type is consistent throughout the instance4344System.out.println("\nInteger container:");4546Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Info: Container holding: String Integer container: Integer container:public boolean isEmpty()
pass 1 of 415public boolean isEmpty() {16 return itemnull == null;17}All 4 passes — pass 1 is the card above pass item1 null 2 null 3 42 4 42 System.out.println(" Empty: " + intContainer.isEmpty());
46Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Empty: trueSystem.out.println(" Empty: " + intContainer.isEmpty());
46Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Empty: truethis.item ← 42
pass 2 of 25public void store(T item42) {6 this.item→ 42 = item42;7 System.out.println(" Stored: " + item42);8}output Stored: 42System.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();System.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();output Empty: falseSystem.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();output Empty: falsepublic T retrieve()
pass 2 of 210public T retrieve() {11 System.out.println(" Retrieved: " + item42);12 return item42;13}output Retrieved: 42System.out.println(" Value: " + num);
50int num = intContainer.retrieve();51System.out.println(" Value: " + num42);5253System.out.println("\nPair class:");output Value: 42 Value: 42 Pair class: Pair class:this.first ← Alice, this.second ← Bob
59public Pair(T firstAlice, T secondBob) {60 this.first→ Alice = firstAlice;61 this.second→ Bob = secondBob;62}public void display()
pass 1 of 278public void display() {79 System.out.println(" First: " + firstAlice + ", Second: " + secondBob);80}output First: Alice, Second: Bobtemp ← Alice, first ← Bob, second ← Alice
72public void swap() {73 T temp→ Alice = first;74 first→ Bob = secondBob;75 second→ Alice = tempAlice;76}System.out.println(" After swap:");
85namePair.swap();86System.out.println(" After swap:");87namePair.display();output After swap: After swap:public void display()
pass 2 of 278public void display() {79 System.out.println(" First: " + firstBob + ", Second: " + secondAlice);80}output First: Bob, Second: AliceSystem.out.println(" Point class:");
89System.out.println("\nPoint class:");9091class Point<T extends Number> {92 private T x;93 private T y;94 95 public Point(T x, T y) {96 this.x = x;97 this.y = y;98 }99 100 public T getX() { return x; }101 public T getY() { return y; }102 103 public double distance() {104 double dx = x.doubleValue();105 double dy = y.doubleValue();106 return Math.sqrt(dx * dx + dy * dy);107 }108 109 public void display() {110 System.out.println(" Point(" + x + ", " + y + ")");111 }112}113114int pointX = 5;115Point<Integer> intPoint = new Point<>(pointX, 4);116intPoint.display();output Point class: Point class:this.x ← 5, this.y ← 4
pass 1 of 295public Point(T x5, T y4) {96 this.x→ 5 = x5;97 this.y→ 4 = y4;98}intPoint ← ⟨GenericWithMethods$1Point A⟩
114int pointX = 5;115Point<Integer> intPoint→ ⟨GenericWithMethods$1Point A⟩ = new Point<>(pointX, 4);116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());public void display()
pass 1 of 2109public void display() {110 System.out.println(" Point(" + x5 + ", " + y4 + ")");111}output Point(5, 4)intPoint.display();
115Point<Integer> intPoint = new Point<>(pointX, 4);116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());dx ← 5.0, dy ← 4.0
pass 1 of 2103public double distance() {104 double dx→ 5.0 = x.doubleValue();105 double dy→ 4.0 = y.doubleValue();106 return Math.sqrt(dx5.0 * dx + dy4.0 * dy);107}System.out.println(" Distance: " + intPoint.distance());
116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());118119Point<Double> doublePoint = new Point<>(1.5, 2.5);120doublePoint.display();output Distance: 6.4031242374328485this.x ← 1.5, this.y ← 2.5
pass 2 of 295public Point(T x1.5, T y2.5) {96 this.x→ 1.5 = x1.5;97 this.y→ 2.5 = y2.5;98}doublePoint ← ⟨GenericWithMethods$1Point B⟩
119Point<Double> doublePoint→ ⟨GenericWithMethods$1Point B⟩ = new Point<>(1.5, 2.5);120doublePoint.display();121System.out.println(" Distance: " + doublePoint.distance());public void display()
pass 2 of 2109public void display() {110 System.out.println(" Point(" + x1.5 + ", " + y2.5 + ")");111}output Point(1.5, 2.5)doublePoint.display();
119 Point<Double> doublePoint = new Point<>(1.5, 2.5);120 doublePoint.display();121 System.out.println(" Distance: " + doublePoint.distance());122}dx ← 1.5, dy ← 2.5
pass 2 of 2103public double distance() {104 double dx→ 1.5 = x.doubleValue();105 double dy→ 2.5 = y.doubleValue();106 return Math.sqrt(dx1.5 * dx + dy2.5 * dy);107}System.out.println(" Distance: " + doublePoint.distance());
120 doublePoint.display();121 System.out.println(" Distance: " + doublePoint.distance());122}output Distance: 2.9154759474226504
public static void main(String[] args)
32public static void main(String[] args) {33 System.out.println("Generic methods:\n");outputGeneric methods: Generic methods:this.item ← Hello
pass 1 of 25public void store(T itemHello) {6 this.item→ Hello = itemHello;7 System.out.println(" Stored: " + itemHello);8}output Stored: Hellopublic T retrieve()
pass 1 of 210public T retrieve() {11 System.out.println(" Retrieved: " + itemHello);12 return itemHello;13}output Retrieved: HelloSystem.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());System.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());output Info: Container holding: StringSystem.out.println(" Info: " + strContainer.getInfo());
37String value = strContainer.retrieve();38System.out.println(" Info: " + strContainer.getInfo());3940// Methods in generic class can use type parameter T41// Parameters and return types can be T42// Type is consistent throughout the instance4344System.out.println("\nInteger container:");4546Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Info: Container holding: String Integer container: Integer container:public boolean isEmpty()
pass 1 of 415public boolean isEmpty() {16 return itemnull == null;17}All 4 passes — pass 1 is the card above pass item1 null 2 null 3 42 4 42 System.out.println(" Empty: " + intContainer.isEmpty());
46Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Empty: trueSystem.out.println(" Empty: " + intContainer.isEmpty());
46Container<Integer> intContainer = new Container<>();47System.out.println(" Empty: " + intContainer.isEmpty());48intContainer.store(42);output Empty: truethis.item ← 42
pass 2 of 25public void store(T item42) {6 this.item→ 42 = item42;7 System.out.println(" Stored: " + item42);8}output Stored: 42System.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();System.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();output Empty: falseSystem.out.println(" Empty: " + intContainer.isEmpty());
48intContainer.store(42);49System.out.println(" Empty: " + intContainer.isEmpty());50int num = intContainer.retrieve();output Empty: falsepublic T retrieve()
pass 2 of 210public T retrieve() {11 System.out.println(" Retrieved: " + item42);12 return item42;13}output Retrieved: 42System.out.println(" Value: " + num);
50int num = intContainer.retrieve();51System.out.println(" Value: " + num42);5253System.out.println("\nPair class:");output Value: 42 Value: 42 Pair class: Pair class:this.first ← Alice, this.second ← Bob
59public Pair(T firstAlice, T secondBob) {60 this.first→ Alice = firstAlice;61 this.second→ Bob = secondBob;62}public void display()
pass 1 of 278public void display() {79 System.out.println(" First: " + firstAlice + ", Second: " + secondBob);80}output First: Alice, Second: Bobtemp ← Alice, first ← Bob, second ← Alice
72public void swap() {73 T temp→ Alice = first;74 first→ Bob = secondBob;75 second→ Alice = tempAlice;76}System.out.println(" After swap:");
85namePair.swap();86System.out.println(" After swap:");87namePair.display();output After swap: After swap:public void display()
pass 2 of 278public void display() {79 System.out.println(" First: " + firstBob + ", Second: " + secondAlice);80}output First: Bob, Second: AliceSystem.out.println(" Point class:");
89System.out.println("\nPoint class:");9091class Point<T extends Number> {92 private T x;93 private T y;94 95 public Point(T x, T y) {96 this.x = x;97 this.y = y;98 }99 100 public T getX() { return x; }101 public T getY() { return y; }102 103 public double distance() {104 double dx = x.doubleValue();105 double dy = y.doubleValue();106 return Math.sqrt(dx * dx + dy * dy);107 }108 109 public void display() {110 System.out.println(" Point(" + x + ", " + y + ")");111 }112}113114int pointX = 6;115Point<Integer> intPoint = new Point<>(pointX, 4);116intPoint.display();output Point class: Point class:this.x ← 6, this.y ← 4
pass 1 of 295public Point(T x6, T y4) {96 this.x→ 6 = x6;97 this.y→ 4 = y4;98}intPoint ← ⟨GenericWithMethods$1Point A⟩
114int pointX = 6;115Point<Integer> intPoint→ ⟨GenericWithMethods$1Point A⟩ = new Point<>(pointX, 4);116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());public void display()
pass 1 of 2109public void display() {110 System.out.println(" Point(" + x6 + ", " + y4 + ")");111}output Point(6, 4)intPoint.display();
115Point<Integer> intPoint = new Point<>(pointX, 4);116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());dx ← 6.0, dy ← 4.0
pass 1 of 2103public double distance() {104 double dx→ 6.0 = x.doubleValue();105 double dy→ 4.0 = y.doubleValue();106 return Math.sqrt(dx6.0 * dx + dy4.0 * dy);107}System.out.println(" Distance: " + intPoint.distance());
116intPoint.display();117System.out.println(" Distance: " + intPoint.distance());118119Point<Double> doublePoint = new Point<>(1.5, 2.5);120doublePoint.display();output Distance: 7.211102550927978this.x ← 1.5, this.y ← 2.5
pass 2 of 295public Point(T x1.5, T y2.5) {96 this.x→ 1.5 = x1.5;97 this.y→ 2.5 = y2.5;98}doublePoint ← ⟨GenericWithMethods$1Point B⟩
119Point<Double> doublePoint→ ⟨GenericWithMethods$1Point B⟩ = new Point<>(1.5, 2.5);120doublePoint.display();121System.out.println(" Distance: " + doublePoint.distance());public void display()
pass 2 of 2109public void display() {110 System.out.println(" Point(" + x1.5 + ", " + y2.5 + ")");111}output Point(1.5, 2.5)doublePoint.display();
119 Point<Double> doublePoint = new Point<>(1.5, 2.5);120 doublePoint.display();121 System.out.println(" Distance: " + doublePoint.distance());122}dx ← 1.5, dy ← 2.5
pass 2 of 2103public double distance() {104 double dx→ 1.5 = x.doubleValue();105 double dy→ 2.5 = y.doubleValue();106 return Math.sqrt(dx1.5 * dx + dy2.5 * dy);107}System.out.println(" Distance: " + doublePoint.distance());
120 doublePoint.display();121 System.out.println(" Distance: " + doublePoint.distance());122}output Distance: 2.9154759474226504
Type parameter T available in fields, methods, and return types.
Multiple type parameters
Use more than one type parameter.
import java.util.*;
public class MultipleTypeParams {
static class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public void display() {
System.out.println(" " + key + " -> " + value);
}
}
public static void main(String[] args) {
System.out.println("Multiple type parameters:\n");
Pair<String, Integer> agePair = new Pair<>("Alice", 30);
agePair.display();
Pair<Integer, String> namePair = new Pair<>(1, "Bob");
namePair.display();
Pair<String, Double> pricePair = new Pair<>("Coffee", 3.50);
pricePair.display();
// Multiple type parameters separated by commas: <K, V>
// Each can be a different type
// Common in key-value data structures
System.out.println("\nSimple map:");
class SimpleMap<K, V> {
private List<K> keys = new ArrayList<>();
private List<V> values = new ArrayList<>();
public void put(K key, V value) {
keys.add(key);
values.add(value);
}
public V get(K key) {
int index = keys.indexOf(key);
return index >= 0 ? values.get(index) : null;
}
public void display() {
for (int i = 0; i < keys.size(); i++) {
System.out.println(" " + keys.get(i) + " = " + values.get(i));
}
}
}
SimpleMap<String, Integer> scores = new SimpleMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.put("Charlie", 92);
scores.display();
String lookupName = "Alice";
System.out.println(" " + lookupName + "'s score: " + scores.get(lookupName));
System.out.println("\nTriple class:");
class Triple<A, B, C> {
private A first;
private B second;
private C third;
public Triple(A first, B second, C third) {
this.first = first;
this.second = second;
this.third = third;
}
public A getFirst() { return first; }
public B getSecond() { return second; }
public C getThird() { return third; }
public void display() {
System.out.println(" (" + first + ", " + second + ", " + third + ")");
}
}
Triple<String, Integer, Double> studentRecord =
new Triple<>("Alice", 20, 3.8);
studentRecord.display();
Triple<Integer, String, Boolean> config =
new Triple<>(8080, "localhost", true);
config.display();
System.out.println("\nEntry class:");
class Entry<K, V> {
private K key;
private V value;
private long timestamp;
public Entry(K key, V value) {
this.key = key;
this.value = value;
this.timestamp = 1000L;
}
public K getKey() { return key; }
public V getValue() { return value; }
public void setValue(V value) {
this.value = value;
this.timestamp = 1001L;
}
public void display() {
System.out.println(" " + key + ": " + value +
" (ts: " + timestamp + ")");
}
}
Entry<String, String> config1 = new Entry<>("host", "localhost");
config1.display();
Entry<Integer, List<String>> userTags =
new Entry<>(101, Arrays.asList("admin", "active"));
userTags.display();
}
}
import java.util.*;
public class MultipleTypeParams {
static class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public void display() {
System.out.println(" " + key + " -> " + value);
}
}
public static void main(String[] args) {
System.out.println("Multiple type parameters:\n");
Pair<String, Integer> agePair = new Pair<>("Alice", 30);
agePair.display();
Pair<Integer, String> namePair = new Pair<>(1, "Bob");
namePair.display();
Pair<String, Double> pricePair = new Pair<>("Coffee", 3.50);
pricePair.display();
// Multiple type parameters separated by commas: <K, V>
// Each can be a different type
// Common in key-value data structures
System.out.println("\nSimple map:");
class SimpleMap<K, V> {
private List<K> keys = new ArrayList<>();
private List<V> values = new ArrayList<>();
public void put(K key, V value) {
keys.add(key);
values.add(value);
}
public V get(K key) {
int index = keys.indexOf(key);
return index >= 0 ? values.get(index) : null;
}
public void display() {
for (int i = 0; i < keys.size(); i++) {
System.out.println(" " + keys.get(i) + " = " + values.get(i));
}
}
}
SimpleMap<String, Integer> scores = new SimpleMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.put("Charlie", 92);
scores.display();
String lookupName = "Bob";
System.out.println(" " + lookupName + "'s score: " + scores.get(lookupName));
System.out.println("\nTriple class:");
class Triple<A, B, C> {
private A first;
private B second;
private C third;
public Triple(A first, B second, C third) {
this.first = first;
this.second = second;
this.third = third;
}
public A getFirst() { return first; }
public B getSecond() { return second; }
public C getThird() { return third; }
public void display() {
System.out.println(" (" + first + ", " + second + ", " + third + ")");
}
}
Triple<String, Integer, Double> studentRecord =
new Triple<>("Alice", 20, 3.8);
studentRecord.display();
Triple<Integer, String, Boolean> config =
new Triple<>(8080, "localhost", true);
config.display();
System.out.println("\nEntry class:");
class Entry<K, V> {
private K key;
private V value;
private long timestamp;
public Entry(K key, V value) {
this.key = key;
this.value = value;
this.timestamp = 1000L;
}
public K getKey() { return key; }
public V getValue() { return value; }
public void setValue(V value) {
this.value = value;
this.timestamp = 1001L;
}
public void display() {
System.out.println(" " + key + ": " + value +
" (ts: " + timestamp + ")");
}
}
Entry<String, String> config1 = new Entry<>("host", "localhost");
config1.display();
Entry<Integer, List<String>> userTags =
new Entry<>(101, Arrays.asList("admin", "active"));
userTags.display();
}
}
import java.util.*;
public class MultipleTypeParams {
static class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public void display() {
System.out.println(" " + key + " -> " + value);
}
}
public static void main(String[] args) {
System.out.println("Multiple type parameters:\n");
Pair<String, Integer> agePair = new Pair<>("Alice", 30);
agePair.display();
Pair<Integer, String> namePair = new Pair<>(1, "Bob");
namePair.display();
Pair<String, Double> pricePair = new Pair<>("Coffee", 3.50);
pricePair.display();
// Multiple type parameters separated by commas: <K, V>
// Each can be a different type
// Common in key-value data structures
System.out.println("\nSimple map:");
class SimpleMap<K, V> {
private List<K> keys = new ArrayList<>();
private List<V> values = new ArrayList<>();
public void put(K key, V value) {
keys.add(key);
values.add(value);
}
public V get(K key) {
int index = keys.indexOf(key);
return index >= 0 ? values.get(index) : null;
}
public void display() {
for (int i = 0; i < keys.size(); i++) {
System.out.println(" " + keys.get(i) + " = " + values.get(i));
}
}
}
SimpleMap<String, Integer> scores = new SimpleMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.put("Charlie", 92);
scores.display();
String lookupName = "Charlie";
System.out.println(" " + lookupName + "'s score: " + scores.get(lookupName));
System.out.println("\nTriple class:");
class Triple<A, B, C> {
private A first;
private B second;
private C third;
public Triple(A first, B second, C third) {
this.first = first;
this.second = second;
this.third = third;
}
public A getFirst() { return first; }
public B getSecond() { return second; }
public C getThird() { return third; }
public void display() {
System.out.println(" (" + first + ", " + second + ", " + third + ")");
}
}
Triple<String, Integer, Double> studentRecord =
new Triple<>("Alice", 20, 3.8);
studentRecord.display();
Triple<Integer, String, Boolean> config =
new Triple<>(8080, "localhost", true);
config.display();
System.out.println("\nEntry class:");
class Entry<K, V> {
private K key;
private V value;
private long timestamp;
public Entry(K key, V value) {
this.key = key;
this.value = value;
this.timestamp = 1000L;
}
public K getKey() { return key; }
public V getValue() { return value; }
public void setValue(V value) {
this.value = value;
this.timestamp = 1001L;
}
public void display() {
System.out.println(" " + key + ": " + value +
" (ts: " + timestamp + ")");
}
}
Entry<String, String> config1 = new Entry<>("host", "localhost");
config1.display();
Entry<Integer, List<String>> userTags =
new Entry<>(101, Arrays.asList("admin", "active"));
userTags.display();
}
}
public static void main(String[] args)
26public static void main(String[] args) {27 System.out.println("Multiple type parameters:\n");outputMultiple type parameters: Multiple type parameters:this.key ← Alice, this.value ← 30
pass 1 of 38public Pair(K keyAlice, V value30) {9 this.key→ Alice = keyAlice;10 this.value→ 30 = value30;11}All 3 passes — pass 1 is the card above pass keyvaluethis.keythis.value1 Alice 30 Alice 30 2 1 Bob 1 Bob 3 Coffee 3.5 Coffee 3.5 public void display()
pass 1 of 321public void display() {22 System.out.println(" " + keyAlice + " -> " + value30);23}output Alice -> 30All 3 passes — pass 1 is the card above pass keyvalue1 Alice 30 2 1 Bob 3 Coffee 3.5 System.out.println(" Simple map:");
42System.out.println("\nSimple map:");output Simple map: Simple map:public void put(K key, V value)
pass 1 of 348public void put(K keyAlice, V value95) {49 keys.add(keyAlice);50 values.add(value95);51}All 3 passes — pass 1 is the card above pass keyvalue1 Alice 95 2 Bob 87 3 Charlie 92 for (int i = 0; i < keys.size(); i++)
pass 1 of 358public void display() {59 for (int i0 = 0; i < keys.size(); i++) {60 System.out.println(" " + keys.get(i0) + " = " + values.get(i));61 }output Alice = 95All 3 passes — pass 1 is the card above pass i1 0 2 1 3 2 System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Alice"; //@lookupName="Alice", "Bob", "Charlie"72System.out.println(" " + lookupNameAlice + "'s score: " + scores.get(lookupName));index ← 0
pass 1 of 253public V get(K keyAlice) {54 int index→ 0 = keys.indexOf(keyAlice);55 return index0 >= 0 ? values.get(index) : null;56}System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Alice"; //@lookupName="Alice", "Bob", "Charlie"72System.out.println(" " + lookupNameAlice + "'s score: " + scores.get(lookupName));output Alice's score: 95index ← 0
pass 2 of 253public V get(K keyAlice) {54 int index→ 0 = keys.indexOf(keyAlice);55 return index0 >= 0 ? values.get(index) : null;56}System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Alice"; //@lookupName="Alice", "Bob", "Charlie"72System.out.println(" " + lookupNameAlice + "'s score: " + scores.get(lookupName));7374System.out.println("\nTriple class:");output Alice's score: 95 Triple class: Triple class:this.first ← Alice, this.second ← 20, this.third ← 3.8
pass 1 of 281public Triple(A firstAlice, B second20, C third3.8) {82 this.first→ Alice = firstAlice;83 this.second→ 20 = second20;84 this.third→ 3.8 = third3.8;85}public void display()
pass 1 of 291public void display() {92 System.out.println(" (" + firstAlice + ", " + second20 + ", " + third3.8 + ")");93}output (Alice, 20, 3.8)this.first ← 8080, this.second ← localhost, this.third ← true
pass 2 of 281public Triple(A first8080, B secondlocalhost, C thirdtrue) {82 this.first→ 8080 = first8080;83 this.second→ localhost = secondlocalhost;84 this.third→ true = thirdtrue;85}public void display()
pass 2 of 291public void display() {92 System.out.println(" (" + first8080 + ", " + secondlocalhost + ", " + thirdtrue + ")");93}output (8080, localhost, true)System.out.println(" Entry class:");
104System.out.println("\nEntry class:");output Entry class: Entry class:this.key ← host, this.value ← localhost, this.timestamp ← 1000
pass 1 of 2111public Entry(K keyhost, V valuelocalhost) {112 this.key→ host = keyhost;113 this.value→ localhost = valuelocalhost;114 this.timestamp→ 1000 = 1000L;115}config1.display();
131Entry<String, String> config1 = new Entry<>("host", "localhost");132config1.display();public void display()
pass 1 of 2125public void display() {126 System.out.println(" " + keyhost + ": " + valuelocalhost + 127 " (ts: " + timestamp1000 + ")");128}output host: localhost (ts: 1000)config1.display();
131Entry<String, String> config1 = new Entry<>("host", "localhost");132config1.display();133134Entry<Integer, List<String>> userTags = 135 new Entry<>(101, Arrays.asList("admin", "active"));136userTags.display();this.key ← 101, this.value ← [admin, active], this.timestamp ← 1000
pass 2 of 2111public Entry(K key101, V value[admin, active]) {112 this.key→ 101 = key101;113 this.value→ [admin, active] = value[admin, active];114 this.timestamp→ 1000 = 1000L;115}userTags ← ⟨MultipleTypeParams$1Entry A⟩
134 Entry<Integer, List<String>> userTags→ ⟨MultipleTypeParams$1Entry A⟩ = 135 new Entry<>(101, Arrays.asList("admin", "active"));136 userTags.display();137}public void display()
pass 2 of 2125public void display() {126 System.out.println(" " + key101 + ": " + value[admin, active] + 127 " (ts: " + timestamp1000 + ")");128}output 101: [admin, active] (ts: 1000)userTags.display();
135 new Entry<>(101, Arrays.asList("admin", "active"));136 userTags.display();137}
public static void main(String[] args)
26public static void main(String[] args) {27 System.out.println("Multiple type parameters:\n");outputMultiple type parameters: Multiple type parameters:this.key ← Alice, this.value ← 30
pass 1 of 38public Pair(K keyAlice, V value30) {9 this.key→ Alice = keyAlice;10 this.value→ 30 = value30;11}All 3 passes — pass 1 is the card above pass keyvaluethis.keythis.value1 Alice 30 Alice 30 2 1 Bob 1 Bob 3 Coffee 3.5 Coffee 3.5 public void display()
pass 1 of 321public void display() {22 System.out.println(" " + keyAlice + " -> " + value30);23}output Alice -> 30All 3 passes — pass 1 is the card above pass keyvalue1 Alice 30 2 1 Bob 3 Coffee 3.5 System.out.println(" Simple map:");
42System.out.println("\nSimple map:");output Simple map: Simple map:public void put(K key, V value)
pass 1 of 348public void put(K keyAlice, V value95) {49 keys.add(keyAlice);50 values.add(value95);51}All 3 passes — pass 1 is the card above pass keyvalue1 Alice 95 2 Bob 87 3 Charlie 92 for (int i = 0; i < keys.size(); i++)
pass 1 of 358public void display() {59 for (int i0 = 0; i < keys.size(); i++) {60 System.out.println(" " + keys.get(i0) + " = " + values.get(i));61 }output Alice = 95All 3 passes — pass 1 is the card above pass i1 0 2 1 3 2 System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Bob";72System.out.println(" " + lookupNameBob + "'s score: " + scores.get(lookupName));index ← 1
pass 1 of 253public V get(K keyBob) {54 int index→ 1 = keys.indexOf(keyBob);55 return index1 >= 0 ? values.get(index) : null;56}System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Bob";72System.out.println(" " + lookupNameBob + "'s score: " + scores.get(lookupName));output Bob's score: 87index ← 1
pass 2 of 253public V get(K keyBob) {54 int index→ 1 = keys.indexOf(keyBob);55 return index1 >= 0 ? values.get(index) : null;56}System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Bob";72System.out.println(" " + lookupNameBob + "'s score: " + scores.get(lookupName));7374System.out.println("\nTriple class:");output Bob's score: 87 Triple class: Triple class:this.first ← Alice, this.second ← 20, this.third ← 3.8
pass 1 of 281public Triple(A firstAlice, B second20, C third3.8) {82 this.first→ Alice = firstAlice;83 this.second→ 20 = second20;84 this.third→ 3.8 = third3.8;85}public void display()
pass 1 of 291public void display() {92 System.out.println(" (" + firstAlice + ", " + second20 + ", " + third3.8 + ")");93}output (Alice, 20, 3.8)this.first ← 8080, this.second ← localhost, this.third ← true
pass 2 of 281public Triple(A first8080, B secondlocalhost, C thirdtrue) {82 this.first→ 8080 = first8080;83 this.second→ localhost = secondlocalhost;84 this.third→ true = thirdtrue;85}public void display()
pass 2 of 291public void display() {92 System.out.println(" (" + first8080 + ", " + secondlocalhost + ", " + thirdtrue + ")");93}output (8080, localhost, true)System.out.println(" Entry class:");
104System.out.println("\nEntry class:");output Entry class: Entry class:this.key ← host, this.value ← localhost, this.timestamp ← 1000
pass 1 of 2111public Entry(K keyhost, V valuelocalhost) {112 this.key→ host = keyhost;113 this.value→ localhost = valuelocalhost;114 this.timestamp→ 1000 = 1000L;115}config1.display();
131Entry<String, String> config1 = new Entry<>("host", "localhost");132config1.display();public void display()
pass 1 of 2125public void display() {126 System.out.println(" " + keyhost + ": " + valuelocalhost + 127 " (ts: " + timestamp1000 + ")");128}output host: localhost (ts: 1000)config1.display();
131Entry<String, String> config1 = new Entry<>("host", "localhost");132config1.display();133134Entry<Integer, List<String>> userTags = 135 new Entry<>(101, Arrays.asList("admin", "active"));136userTags.display();this.key ← 101, this.value ← [admin, active], this.timestamp ← 1000
pass 2 of 2111public Entry(K key101, V value[admin, active]) {112 this.key→ 101 = key101;113 this.value→ [admin, active] = value[admin, active];114 this.timestamp→ 1000 = 1000L;115}userTags ← ⟨MultipleTypeParams$1Entry A⟩
134 Entry<Integer, List<String>> userTags→ ⟨MultipleTypeParams$1Entry A⟩ = 135 new Entry<>(101, Arrays.asList("admin", "active"));136 userTags.display();137}public void display()
pass 2 of 2125public void display() {126 System.out.println(" " + key101 + ": " + value[admin, active] + 127 " (ts: " + timestamp1000 + ")");128}output 101: [admin, active] (ts: 1000)userTags.display();
135 new Entry<>(101, Arrays.asList("admin", "active"));136 userTags.display();137}
public static void main(String[] args)
26public static void main(String[] args) {27 System.out.println("Multiple type parameters:\n");outputMultiple type parameters: Multiple type parameters:this.key ← Alice, this.value ← 30
pass 1 of 38public Pair(K keyAlice, V value30) {9 this.key→ Alice = keyAlice;10 this.value→ 30 = value30;11}All 3 passes — pass 1 is the card above pass keyvaluethis.keythis.value1 Alice 30 Alice 30 2 1 Bob 1 Bob 3 Coffee 3.5 Coffee 3.5 public void display()
pass 1 of 321public void display() {22 System.out.println(" " + keyAlice + " -> " + value30);23}output Alice -> 30All 3 passes — pass 1 is the card above pass keyvalue1 Alice 30 2 1 Bob 3 Coffee 3.5 System.out.println(" Simple map:");
42System.out.println("\nSimple map:");output Simple map: Simple map:public void put(K key, V value)
pass 1 of 348public void put(K keyAlice, V value95) {49 keys.add(keyAlice);50 values.add(value95);51}All 3 passes — pass 1 is the card above pass keyvalue1 Alice 95 2 Bob 87 3 Charlie 92 for (int i = 0; i < keys.size(); i++)
pass 1 of 358public void display() {59 for (int i0 = 0; i < keys.size(); i++) {60 System.out.println(" " + keys.get(i0) + " = " + values.get(i));61 }output Alice = 95All 3 passes — pass 1 is the card above pass i1 0 2 1 3 2 System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Charlie";72System.out.println(" " + lookupNameCharlie + "'s score: " + scores.get(lookupName));index ← 2
pass 1 of 253public V get(K keyCharlie) {54 int index→ 2 = keys.indexOf(keyCharlie);55 return index2 >= 0 ? values.get(index) : null;56}System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Charlie";72System.out.println(" " + lookupNameCharlie + "'s score: " + scores.get(lookupName));output Charlie's score: 92index ← 2
pass 2 of 253public V get(K keyCharlie) {54 int index→ 2 = keys.indexOf(keyCharlie);55 return index2 >= 0 ? values.get(index) : null;56}System.out.println(" " + lookupName + "'s score: " + scores.get(looku…
71String lookupName = "Charlie";72System.out.println(" " + lookupNameCharlie + "'s score: " + scores.get(lookupName));7374System.out.println("\nTriple class:");output Charlie's score: 92 Triple class: Triple class:this.first ← Alice, this.second ← 20, this.third ← 3.8
pass 1 of 281public Triple(A firstAlice, B second20, C third3.8) {82 this.first→ Alice = firstAlice;83 this.second→ 20 = second20;84 this.third→ 3.8 = third3.8;85}public void display()
pass 1 of 291public void display() {92 System.out.println(" (" + firstAlice + ", " + second20 + ", " + third3.8 + ")");93}output (Alice, 20, 3.8)this.first ← 8080, this.second ← localhost, this.third ← true
pass 2 of 281public Triple(A first8080, B secondlocalhost, C thirdtrue) {82 this.first→ 8080 = first8080;83 this.second→ localhost = secondlocalhost;84 this.third→ true = thirdtrue;85}public void display()
pass 2 of 291public void display() {92 System.out.println(" (" + first8080 + ", " + secondlocalhost + ", " + thirdtrue + ")");93}output (8080, localhost, true)System.out.println(" Entry class:");
104System.out.println("\nEntry class:");output Entry class: Entry class:this.key ← host, this.value ← localhost, this.timestamp ← 1000
pass 1 of 2111public Entry(K keyhost, V valuelocalhost) {112 this.key→ host = keyhost;113 this.value→ localhost = valuelocalhost;114 this.timestamp→ 1000 = 1000L;115}config1.display();
131Entry<String, String> config1 = new Entry<>("host", "localhost");132config1.display();public void display()
pass 1 of 2125public void display() {126 System.out.println(" " + keyhost + ": " + valuelocalhost + 127 " (ts: " + timestamp1000 + ")");128}output host: localhost (ts: 1000)config1.display();
131Entry<String, String> config1 = new Entry<>("host", "localhost");132config1.display();133134Entry<Integer, List<String>> userTags = 135 new Entry<>(101, Arrays.asList("admin", "active"));136userTags.display();this.key ← 101, this.value ← [admin, active], this.timestamp ← 1000
pass 2 of 2111public Entry(K key101, V value[admin, active]) {112 this.key→ 101 = key101;113 this.value→ [admin, active] = value[admin, active];114 this.timestamp→ 1000 = 1000L;115}userTags ← ⟨MultipleTypeParams$1Entry A⟩
134 Entry<Integer, List<String>> userTags→ ⟨MultipleTypeParams$1Entry A⟩ = 135 new Entry<>(101, Arrays.asList("admin", "active"));136 userTags.display();137}public void display()
pass 2 of 2125public void display() {126 System.out.println(" " + key101 + ": " + value[admin, active] + 127 " (ts: " + timestamp1000 + ")");128}output 101: [admin, active] (ts: 1000)userTags.display();
135 new Entry<>(101, Arrays.asList("admin", "active"));136 userTags.display();137}
class Pair<K, V> - K for key, V for value. Like Map entries.
Generic interface
Define interfaces with type parameters.
import java.util.*;
public class GenericInterface {
interface Container<T> {
void add(T item);
T get(int index);
int size();
boolean isEmpty();
}
static class ListContainer<T> implements Container<T> {
private List<T> items = new ArrayList<>();
@Override
public void add(T item) {
items.add(item);
System.out.println(" Added: " + item);
}
@Override
public T get(int index) {
return items.get(index);
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
}
public static void main(String[] args) {
System.out.println("Generic interface:\n");
Container<String> strContainer = new ListContainer<>();
strContainer.add("Apple");
strContainer.add("Banana");
strContainer.add("Cherry");
System.out.println(" Size: " + strContainer.size());
System.out.println(" First: " + strContainer.get(0));
// Interfaces can have type parameters
// Implementing class specifies type or remains generic
// Same type safety benefits as generic classes
System.out.println("\nStorage interface:");
interface Storage<T> {
void store(T item);
T retrieve();
void clear();
}
class MemoryStorage<T> implements Storage<T> {
private T item;
@Override
public void store(T item) {
this.item = item;
System.out.println(" Stored: " + item);
}
@Override
public T retrieve() {
return item;
}
@Override
public void clear() {
item = null;
System.out.println(" Cleared");
}
}
Storage<Integer> intStorage = new MemoryStorage<>();
intStorage.store(42);
int value = intStorage.retrieve();
System.out.println(" Retrieved: " + value);
System.out.println("\nConcrete implementation:");
class StringContainer implements Container<String> {
private List<String> items = new ArrayList<>();
@Override
public void add(String item) {
items.add(item.toUpperCase());
System.out.println(" Added (upper): " + item);
}
@Override
public String get(int index) {
return items.get(index);
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
}
Container<String> concrete = new StringContainer();
concrete.add("hello");
concrete.add("world");
System.out.println(" First: " + concrete.get(0));
System.out.println("\nComparable-like:");
interface Comparable<T> {
int compareTo(T other);
}
class Person implements Comparable<Person> {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Bob", 25);
int result = p1.compareTo(p2);
System.out.println(" " + p1 + " vs " + p2 + ": " + result);
System.out.println("\nRepository pattern:");
interface Repository<T, ID> {
void save(T entity);
T findById(ID id);
}
class UserRepository implements Repository<String, Integer> {
private Map<Integer, String> users = new HashMap<>();
@Override
public void save(String user) {
int id = users.size() + 1;
users.put(id, user);
System.out.println(" Saved user: " + user + " (id=" + id + ")");
}
@Override
public String findById(Integer id) {
return users.get(id);
}
}
Repository<String, Integer> repo = new UserRepository();
repo.save("Alice");
repo.save("Bob");
int lookupId = 1;
String user = repo.findById(lookupId);
System.out.println(" User " + lookupId + ": " + user);
}
}
import java.util.*;
public class GenericInterface {
interface Container<T> {
void add(T item);
T get(int index);
int size();
boolean isEmpty();
}
static class ListContainer<T> implements Container<T> {
private List<T> items = new ArrayList<>();
@Override
public void add(T item) {
items.add(item);
System.out.println(" Added: " + item);
}
@Override
public T get(int index) {
return items.get(index);
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
}
public static void main(String[] args) {
System.out.println("Generic interface:\n");
Container<String> strContainer = new ListContainer<>();
strContainer.add("Apple");
strContainer.add("Banana");
strContainer.add("Cherry");
System.out.println(" Size: " + strContainer.size());
System.out.println(" First: " + strContainer.get(0));
// Interfaces can have type parameters
// Implementing class specifies type or remains generic
// Same type safety benefits as generic classes
System.out.println("\nStorage interface:");
interface Storage<T> {
void store(T item);
T retrieve();
void clear();
}
class MemoryStorage<T> implements Storage<T> {
private T item;
@Override
public void store(T item) {
this.item = item;
System.out.println(" Stored: " + item);
}
@Override
public T retrieve() {
return item;
}
@Override
public void clear() {
item = null;
System.out.println(" Cleared");
}
}
Storage<Integer> intStorage = new MemoryStorage<>();
intStorage.store(42);
int value = intStorage.retrieve();
System.out.println(" Retrieved: " + value);
System.out.println("\nConcrete implementation:");
class StringContainer implements Container<String> {
private List<String> items = new ArrayList<>();
@Override
public void add(String item) {
items.add(item.toUpperCase());
System.out.println(" Added (upper): " + item);
}
@Override
public String get(int index) {
return items.get(index);
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
}
Container<String> concrete = new StringContainer();
concrete.add("hello");
concrete.add("world");
System.out.println(" First: " + concrete.get(0));
System.out.println("\nComparable-like:");
interface Comparable<T> {
int compareTo(T other);
}
class Person implements Comparable<Person> {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Bob", 25);
int result = p1.compareTo(p2);
System.out.println(" " + p1 + " vs " + p2 + ": " + result);
System.out.println("\nRepository pattern:");
interface Repository<T, ID> {
void save(T entity);
T findById(ID id);
}
class UserRepository implements Repository<String, Integer> {
private Map<Integer, String> users = new HashMap<>();
@Override
public void save(String user) {
int id = users.size() + 1;
users.put(id, user);
System.out.println(" Saved user: " + user + " (id=" + id + ")");
}
@Override
public String findById(Integer id) {
return users.get(id);
}
}
Repository<String, Integer> repo = new UserRepository();
repo.save("Alice");
repo.save("Bob");
int lookupId = 2;
String user = repo.findById(lookupId);
System.out.println(" User " + lookupId + ": " + user);
}
}
import java.util.*;
public class GenericInterface {
interface Container<T> {
void add(T item);
T get(int index);
int size();
boolean isEmpty();
}
static class ListContainer<T> implements Container<T> {
private List<T> items = new ArrayList<>();
@Override
public void add(T item) {
items.add(item);
System.out.println(" Added: " + item);
}
@Override
public T get(int index) {
return items.get(index);
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
}
public static void main(String[] args) {
System.out.println("Generic interface:\n");
Container<String> strContainer = new ListContainer<>();
strContainer.add("Apple");
strContainer.add("Banana");
strContainer.add("Cherry");
System.out.println(" Size: " + strContainer.size());
System.out.println(" First: " + strContainer.get(0));
// Interfaces can have type parameters
// Implementing class specifies type or remains generic
// Same type safety benefits as generic classes
System.out.println("\nStorage interface:");
interface Storage<T> {
void store(T item);
T retrieve();
void clear();
}
class MemoryStorage<T> implements Storage<T> {
private T item;
@Override
public void store(T item) {
this.item = item;
System.out.println(" Stored: " + item);
}
@Override
public T retrieve() {
return item;
}
@Override
public void clear() {
item = null;
System.out.println(" Cleared");
}
}
Storage<Integer> intStorage = new MemoryStorage<>();
intStorage.store(42);
int value = intStorage.retrieve();
System.out.println(" Retrieved: " + value);
System.out.println("\nConcrete implementation:");
class StringContainer implements Container<String> {
private List<String> items = new ArrayList<>();
@Override
public void add(String item) {
items.add(item.toUpperCase());
System.out.println(" Added (upper): " + item);
}
@Override
public String get(int index) {
return items.get(index);
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
}
Container<String> concrete = new StringContainer();
concrete.add("hello");
concrete.add("world");
System.out.println(" First: " + concrete.get(0));
System.out.println("\nComparable-like:");
interface Comparable<T> {
int compareTo(T other);
}
class Person implements Comparable<Person> {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Bob", 25);
int result = p1.compareTo(p2);
System.out.println(" " + p1 + " vs " + p2 + ": " + result);
System.out.println("\nRepository pattern:");
interface Repository<T, ID> {
void save(T entity);
T findById(ID id);
}
class UserRepository implements Repository<String, Integer> {
private Map<Integer, String> users = new HashMap<>();
@Override
public void save(String user) {
int id = users.size() + 1;
users.put(id, user);
System.out.println(" Saved user: " + user + " (id=" + id + ")");
}
@Override
public String findById(Integer id) {
return users.get(id);
}
}
Repository<String, Integer> repo = new UserRepository();
repo.save("Alice");
repo.save("Bob");
int lookupId = 3;
String user = repo.findById(lookupId);
System.out.println(" User " + lookupId + ": " + user);
}
}
strContainer ← ⟨GenericInterface$ListContainer A⟩
36public static void main(String[] args) {37 System.out.println("Generic interface:\n");38 39 Container<String> strContainer→ ⟨GenericInterface$ListContainer A⟩ = new ListContainer<>();40 strContainer.add("Apple");41 strContainer.add("Banana");outputGeneric interface:@Override public void add(T item)
pass 1 of 314@Override15public void add(T itemApple) {16 items.add(itemApple);17 System.out.println(" Added: " + itemApple);18}output Added: AppleAll 3 passes — pass 1 is the card above pass item1 Apple 2 Banana 3 Cherry strContainer.add("Apple");
39Container<String> strContainer = new ListContainer<>();40strContainer.add("Apple");41strContainer.add("Banana");42strContainer.add("Cherry");strContainer.add("Banana");
40strContainer.add("Apple");41strContainer.add("Banana");42strContainer.add("Cherry");strContainer.add("Cherry");
41strContainer.add("Banana");42strContainer.add("Cherry");4344System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));System.out.println(" Size: " + strContainer.size());
44System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));output Size: 3@Override public T get(int index)
20@Override21public T get(int index0) {22 return items.get(index0);23}System.out.println(" First: " + strContainer.get(0));
44System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));4647// Interfaces can have type parameters48// Implementing class specifies type or remains generic49// Same type safety benefits as generic classes5051System.out.println("\nStorage interface:");output First: Apple Storage interface:this.item ← 42
62@Override63public void store(T item42) {64 this.item→ 42 = item42;65 System.out.println(" Stored: " + item42);66}output Stored: 42@Override public T retrieve()
68@Override69public T retrieve() {70 return item42;71}System.out.println(" Retrieved: " + value);
82int value = intStorage.retrieve();83System.out.println(" Retrieved: " + value42);8485System.out.println("\nConcrete implementation:");8687class StringContainer implements Container<String> {88 private List<String> items = new ArrayList<>();89 90 @Override91 public void add(String item) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + item);94 }95 96 @Override97 public String get(int index) {98 return items.get(index);99 }100 101 @Override102 public int size() {103 return items.size();104 }105 106 @Override107 public boolean isEmpty() {108 return items.isEmpty();109 }110}111112Container<String> concrete = new StringContainer();113concrete.add("hello");114concrete.add("world");output Retrieved: 42 Retrieved: 42 Concrete implementation: Concrete implementation:@Override public void add(String item)
pass 1 of 290@Override91public void add(String itemhello) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + itemhello);94}output Added (upper): helloconcrete.add("hello");
112Container<String> concrete = new StringContainer();113concrete.add("hello");114concrete.add("world");115System.out.println(" First: " + concrete.get(0));@Override public void add(String item)
pass 2 of 290@Override91public void add(String itemworld) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + itemworld);94}output Added (upper): worldconcrete.add("world");
113concrete.add("hello");114concrete.add("world");115System.out.println(" First: " + concrete.get(0));@Override public String get(int index)
96@Override97public String get(int index0) {98 return items.get(index0);99}System.out.println(" First: " + concrete.get(0));
114concrete.add("world");115System.out.println(" First: " + concrete.get(0));116117System.out.println("\nComparable-like:");output First: HELLO Comparable-like:this.name ← Alice, this.age ← 30
pass 1 of 2127Person(String nameAlice, int age30) {128 this.name→ Alice = nameAlice;129 this.age→ 30 = age30;130}Person p2 = new Person("Bob", 25);
143Person p1 = new Person("Alice", 30);144Person p2 = new Person("Bob", 25);this.name ← Bob, this.age ← 25
pass 2 of 2127Person(String nameBob, int age25) {128 this.name→ Bob = nameBob;129 this.age→ 25 = age25;130}p2 ← Bob (25)
143Person p1 = new Person("Alice", 30);144Person p2→ Bob (25) = new Person("Bob", 25);145146int result = p1.compareTo(p2Bob (25));147System.out.println(" " + p1 + " vs " + p2 + ": " + result);@Override public int compareTo(Person other)
132@Override133public int compareTo(Person otherBob (25)) {134 return Integer.compare(this.age30, other.age25);135}result ← 1
146int result→ 1 = p1.compareTo(p2Bob (25));147System.out.println(" " + p1Alice (30) + " vs " + p2Bob (25) + ": " + result1);148149System.out.println("\nRepository pattern:");150151interface Repository<T, ID> {152 void save(T entity);153 T findById(ID id);154}155156class UserRepository implements Repository<String, Integer> {157 private Map<Integer, String> users = new HashMap<>();158 159 @Override160 public void save(String user) {161 int id = users.size() + 1;162 users.put(id, user);163 System.out.println(" Saved user: " + user + " (id=" + id + ")");164 }165 166 @Override167 public String findById(Integer id) {168 return users.get(id);169 }170}171172Repository<String, Integer> repo = new UserRepository();173repo.save("Alice");174repo.save("Bob");output Alice (30) vs Bob (25): 1 Repository pattern:id ← 1
pass 1 of 2159@Override160public void save(String userAlice) {161 int id→ 1 = users.size() + 1;162 users.put(id1, userAlice);163 System.out.println(" Saved user: " + userAlice + " (id=" + id1 + ")");164}output Saved user: Alice (id=1)repo.save("Alice");
172Repository<String, Integer> repo = new UserRepository();173repo.save("Alice");174repo.save("Bob");175int lookupId = 1; //@lookupId=1, 2, 3id ← 2
pass 2 of 2159@Override160public void save(String userBob) {161 int id→ 2 = users.size() + 1;162 users.put(id2, userBob);163 System.out.println(" Saved user: " + userBob + " (id=" + id2 + ")");164}output Saved user: Bob (id=2)lookupId ← 1
173repo.save("Alice");174repo.save("Bob");175int lookupId→ 1 = 1; //@lookupId=1, 2, 3176String user = repo.findById(lookupId1);177System.out.println(" User " + lookupId + ": " + user);@Override public String findById(Integer id)
166@Override167public String findById(Integer id1) {168 return users.get(id1);169}user ← Alice
175 int lookupId = 1; //@lookupId=1, 2, 3176 String user→ Alice = repo.findById(lookupId1);177 System.out.println(" User " + lookupId1 + ": " + userAlice);178}output User 1: Alice
strContainer ← ⟨GenericInterface$ListContainer A⟩
36public static void main(String[] args) {37 System.out.println("Generic interface:\n");38 39 Container<String> strContainer→ ⟨GenericInterface$ListContainer A⟩ = new ListContainer<>();40 strContainer.add("Apple");41 strContainer.add("Banana");outputGeneric interface:@Override public void add(T item)
pass 1 of 314@Override15public void add(T itemApple) {16 items.add(itemApple);17 System.out.println(" Added: " + itemApple);18}output Added: AppleAll 3 passes — pass 1 is the card above pass item1 Apple 2 Banana 3 Cherry strContainer.add("Apple");
39Container<String> strContainer = new ListContainer<>();40strContainer.add("Apple");41strContainer.add("Banana");42strContainer.add("Cherry");strContainer.add("Banana");
40strContainer.add("Apple");41strContainer.add("Banana");42strContainer.add("Cherry");strContainer.add("Cherry");
41strContainer.add("Banana");42strContainer.add("Cherry");4344System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));System.out.println(" Size: " + strContainer.size());
44System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));output Size: 3@Override public T get(int index)
20@Override21public T get(int index0) {22 return items.get(index0);23}System.out.println(" First: " + strContainer.get(0));
44System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));4647// Interfaces can have type parameters48// Implementing class specifies type or remains generic49// Same type safety benefits as generic classes5051System.out.println("\nStorage interface:");output First: Apple Storage interface:this.item ← 42
62@Override63public void store(T item42) {64 this.item→ 42 = item42;65 System.out.println(" Stored: " + item42);66}output Stored: 42@Override public T retrieve()
68@Override69public T retrieve() {70 return item42;71}System.out.println(" Retrieved: " + value);
82int value = intStorage.retrieve();83System.out.println(" Retrieved: " + value42);8485System.out.println("\nConcrete implementation:");8687class StringContainer implements Container<String> {88 private List<String> items = new ArrayList<>();89 90 @Override91 public void add(String item) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + item);94 }95 96 @Override97 public String get(int index) {98 return items.get(index);99 }100 101 @Override102 public int size() {103 return items.size();104 }105 106 @Override107 public boolean isEmpty() {108 return items.isEmpty();109 }110}111112Container<String> concrete = new StringContainer();113concrete.add("hello");114concrete.add("world");output Retrieved: 42 Retrieved: 42 Concrete implementation: Concrete implementation:@Override public void add(String item)
pass 1 of 290@Override91public void add(String itemhello) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + itemhello);94}output Added (upper): helloconcrete.add("hello");
112Container<String> concrete = new StringContainer();113concrete.add("hello");114concrete.add("world");115System.out.println(" First: " + concrete.get(0));@Override public void add(String item)
pass 2 of 290@Override91public void add(String itemworld) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + itemworld);94}output Added (upper): worldconcrete.add("world");
113concrete.add("hello");114concrete.add("world");115System.out.println(" First: " + concrete.get(0));@Override public String get(int index)
96@Override97public String get(int index0) {98 return items.get(index0);99}System.out.println(" First: " + concrete.get(0));
114concrete.add("world");115System.out.println(" First: " + concrete.get(0));116117System.out.println("\nComparable-like:");output First: HELLO Comparable-like:this.name ← Alice, this.age ← 30
pass 1 of 2127Person(String nameAlice, int age30) {128 this.name→ Alice = nameAlice;129 this.age→ 30 = age30;130}Person p2 = new Person("Bob", 25);
143Person p1 = new Person("Alice", 30);144Person p2 = new Person("Bob", 25);this.name ← Bob, this.age ← 25
pass 2 of 2127Person(String nameBob, int age25) {128 this.name→ Bob = nameBob;129 this.age→ 25 = age25;130}p2 ← Bob (25)
143Person p1 = new Person("Alice", 30);144Person p2→ Bob (25) = new Person("Bob", 25);145146int result = p1.compareTo(p2Bob (25));147System.out.println(" " + p1 + " vs " + p2 + ": " + result);@Override public int compareTo(Person other)
132@Override133public int compareTo(Person otherBob (25)) {134 return Integer.compare(this.age30, other.age25);135}result ← 1
146int result→ 1 = p1.compareTo(p2Bob (25));147System.out.println(" " + p1Alice (30) + " vs " + p2Bob (25) + ": " + result1);148149System.out.println("\nRepository pattern:");150151interface Repository<T, ID> {152 void save(T entity);153 T findById(ID id);154}155156class UserRepository implements Repository<String, Integer> {157 private Map<Integer, String> users = new HashMap<>();158 159 @Override160 public void save(String user) {161 int id = users.size() + 1;162 users.put(id, user);163 System.out.println(" Saved user: " + user + " (id=" + id + ")");164 }165 166 @Override167 public String findById(Integer id) {168 return users.get(id);169 }170}171172Repository<String, Integer> repo = new UserRepository();173repo.save("Alice");174repo.save("Bob");output Alice (30) vs Bob (25): 1 Repository pattern:id ← 1
pass 1 of 2159@Override160public void save(String userAlice) {161 int id→ 1 = users.size() + 1;162 users.put(id1, userAlice);163 System.out.println(" Saved user: " + userAlice + " (id=" + id1 + ")");164}output Saved user: Alice (id=1)repo.save("Alice");
172Repository<String, Integer> repo = new UserRepository();173repo.save("Alice");174repo.save("Bob");175int lookupId = 2;id ← 2
pass 2 of 2159@Override160public void save(String userBob) {161 int id→ 2 = users.size() + 1;162 users.put(id2, userBob);163 System.out.println(" Saved user: " + userBob + " (id=" + id2 + ")");164}output Saved user: Bob (id=2)lookupId ← 2
173repo.save("Alice");174repo.save("Bob");175int lookupId→ 2 = 2;176String user = repo.findById(lookupId2);177System.out.println(" User " + lookupId + ": " + user);@Override public String findById(Integer id)
166@Override167public String findById(Integer id2) {168 return users.get(id2);169}user ← Bob
175 int lookupId = 2;176 String user→ Bob = repo.findById(lookupId2);177 System.out.println(" User " + lookupId2 + ": " + userBob);178}output User 2: Bob
strContainer ← ⟨GenericInterface$ListContainer A⟩
36public static void main(String[] args) {37 System.out.println("Generic interface:\n");38 39 Container<String> strContainer→ ⟨GenericInterface$ListContainer A⟩ = new ListContainer<>();40 strContainer.add("Apple");41 strContainer.add("Banana");outputGeneric interface:@Override public void add(T item)
pass 1 of 314@Override15public void add(T itemApple) {16 items.add(itemApple);17 System.out.println(" Added: " + itemApple);18}output Added: AppleAll 3 passes — pass 1 is the card above pass item1 Apple 2 Banana 3 Cherry strContainer.add("Apple");
39Container<String> strContainer = new ListContainer<>();40strContainer.add("Apple");41strContainer.add("Banana");42strContainer.add("Cherry");strContainer.add("Banana");
40strContainer.add("Apple");41strContainer.add("Banana");42strContainer.add("Cherry");strContainer.add("Cherry");
41strContainer.add("Banana");42strContainer.add("Cherry");4344System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));System.out.println(" Size: " + strContainer.size());
44System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));output Size: 3@Override public T get(int index)
20@Override21public T get(int index0) {22 return items.get(index0);23}System.out.println(" First: " + strContainer.get(0));
44System.out.println(" Size: " + strContainer.size());45System.out.println(" First: " + strContainer.get(0));4647// Interfaces can have type parameters48// Implementing class specifies type or remains generic49// Same type safety benefits as generic classes5051System.out.println("\nStorage interface:");output First: Apple Storage interface:this.item ← 42
62@Override63public void store(T item42) {64 this.item→ 42 = item42;65 System.out.println(" Stored: " + item42);66}output Stored: 42@Override public T retrieve()
68@Override69public T retrieve() {70 return item42;71}System.out.println(" Retrieved: " + value);
82int value = intStorage.retrieve();83System.out.println(" Retrieved: " + value42);8485System.out.println("\nConcrete implementation:");8687class StringContainer implements Container<String> {88 private List<String> items = new ArrayList<>();89 90 @Override91 public void add(String item) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + item);94 }95 96 @Override97 public String get(int index) {98 return items.get(index);99 }100 101 @Override102 public int size() {103 return items.size();104 }105 106 @Override107 public boolean isEmpty() {108 return items.isEmpty();109 }110}111112Container<String> concrete = new StringContainer();113concrete.add("hello");114concrete.add("world");output Retrieved: 42 Retrieved: 42 Concrete implementation: Concrete implementation:@Override public void add(String item)
pass 1 of 290@Override91public void add(String itemhello) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + itemhello);94}output Added (upper): helloconcrete.add("hello");
112Container<String> concrete = new StringContainer();113concrete.add("hello");114concrete.add("world");115System.out.println(" First: " + concrete.get(0));@Override public void add(String item)
pass 2 of 290@Override91public void add(String itemworld) {92 items.add(item.toUpperCase());93 System.out.println(" Added (upper): " + itemworld);94}output Added (upper): worldconcrete.add("world");
113concrete.add("hello");114concrete.add("world");115System.out.println(" First: " + concrete.get(0));@Override public String get(int index)
96@Override97public String get(int index0) {98 return items.get(index0);99}System.out.println(" First: " + concrete.get(0));
114concrete.add("world");115System.out.println(" First: " + concrete.get(0));116117System.out.println("\nComparable-like:");output First: HELLO Comparable-like:this.name ← Alice, this.age ← 30
pass 1 of 2127Person(String nameAlice, int age30) {128 this.name→ Alice = nameAlice;129 this.age→ 30 = age30;130}Person p2 = new Person("Bob", 25);
143Person p1 = new Person("Alice", 30);144Person p2 = new Person("Bob", 25);this.name ← Bob, this.age ← 25
pass 2 of 2127Person(String nameBob, int age25) {128 this.name→ Bob = nameBob;129 this.age→ 25 = age25;130}p2 ← Bob (25)
143Person p1 = new Person("Alice", 30);144Person p2→ Bob (25) = new Person("Bob", 25);145146int result = p1.compareTo(p2Bob (25));147System.out.println(" " + p1 + " vs " + p2 + ": " + result);@Override public int compareTo(Person other)
132@Override133public int compareTo(Person otherBob (25)) {134 return Integer.compare(this.age30, other.age25);135}result ← 1
146int result→ 1 = p1.compareTo(p2Bob (25));147System.out.println(" " + p1Alice (30) + " vs " + p2Bob (25) + ": " + result1);148149System.out.println("\nRepository pattern:");150151interface Repository<T, ID> {152 void save(T entity);153 T findById(ID id);154}155156class UserRepository implements Repository<String, Integer> {157 private Map<Integer, String> users = new HashMap<>();158 159 @Override160 public void save(String user) {161 int id = users.size() + 1;162 users.put(id, user);163 System.out.println(" Saved user: " + user + " (id=" + id + ")");164 }165 166 @Override167 public String findById(Integer id) {168 return users.get(id);169 }170}171172Repository<String, Integer> repo = new UserRepository();173repo.save("Alice");174repo.save("Bob");output Alice (30) vs Bob (25): 1 Repository pattern:id ← 1
pass 1 of 2159@Override160public void save(String userAlice) {161 int id→ 1 = users.size() + 1;162 users.put(id1, userAlice);163 System.out.println(" Saved user: " + userAlice + " (id=" + id1 + ")");164}output Saved user: Alice (id=1)repo.save("Alice");
172Repository<String, Integer> repo = new UserRepository();173repo.save("Alice");174repo.save("Bob");175int lookupId = 3;id ← 2
pass 2 of 2159@Override160public void save(String userBob) {161 int id→ 2 = users.size() + 1;162 users.put(id2, userBob);163 System.out.println(" Saved user: " + userBob + " (id=" + id2 + ")");164}output Saved user: Bob (id=2)lookupId ← 3
173repo.save("Alice");174repo.save("Bob");175int lookupId→ 3 = 3;176String user = repo.findById(lookupId3);177System.out.println(" User " + lookupId + ": " + user);@Override public String findById(Integer id)
166@Override167public String findById(Integer id3) {168 return users.get(id3);169}user ← null
175 int lookupId = 3;176 String user→ null = repo.findById(lookupId3);177 System.out.println(" User " + lookupId3 + ": " + usernull);178}output User 3: null
interface Container<T> - implementations specify the type.
Diamond operator
Let compiler infer type arguments.
import java.util.*;
public class DiamondOperator {
static class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
public static void main(String[] args) {
System.out.println("Diamond operator:\n");
// Before Java 7 (verbose)
Box<String> box1 = new Box<String>("Hello");
System.out.println(" Old way: " + box1.getValue());
// Java 7+ (diamond operator)
Box<String> box2 = new Box<>("World");
System.out.println(" Diamond: " + box2.getValue());
// Diamond operator <> infers type from left side
// Available since Java 7
// Reduces verbosity while maintaining type safety
// Compiler infers the type parameter
System.out.println("\nWith collections:");
// Verbose
List<String> list1 = new ArrayList<String>();
list1.add("Apple");
// Diamond
List<String> list2 = new ArrayList<>();
list2.add("Banana");
Map<String, Integer> map = new LinkedHashMap<>();
map.put("Alice", 30);
map.put("Bob", 25);
System.out.println(" List: " + list2);
System.out.println(" Map: " + map);
System.out.println("\nNested generics:");
// Before Java 7 (very verbose)
Map<String, List<Integer>> map1 =
new HashMap<String, List<Integer>>();
// With diamond (cleaner)
Map<String, List<Integer>> map2 = new LinkedHashMap<>();
map2.put("scores", Arrays.asList(85, 90, 95));
map2.put("ages", Arrays.asList(20, 21, 22));
System.out.println(" Nested map: " + map2);
System.out.println("\nCustom classes:");
class Pair<K, V> {
K key;
V value;
Pair(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return key + "=" + value;
}
}
// Diamond inference
Pair<String, Integer> pair1 = new Pair<>("age", 30);
Pair<Integer, String> pair2 = new Pair<>(1, "first");
System.out.println(" " + pair1);
System.out.println(" " + pair2);
System.out.println("\nReturn type inference:");
class Factory {
static <T> Box<T> createBox(T value) {
return new Box<>(value); // Diamond infers T
}
}
Box<String> strBox = Factory.createBox("Hello");
Box<Integer> intBox = Factory.createBox(42);
System.out.println(" String box: " + strBox.getValue());
System.out.println(" Integer box: " + intBox.getValue());
System.out.println("\nComplex example:");
class Container<T> {
List<T> items;
Container() {
this.items = new ArrayList<>(); // Diamond
}
void add(T item) {
items.add(item);
}
List<T> getItems() {
return items;
}
}
Container<String> container = new Container<>(); // Diamond
container.add("A");
container.add("B");
container.add("C");
System.out.println(" Items: " + container.getItems());
// Nested
List<Container<Integer>> containers = new ArrayList<>();
Container<Integer> c1 = new Container<>();
c1.add(1);
c1.add(2);
containers.add(c1);
System.out.println(" Nested: " + containers.get(0).getItems());
}
}
public static void main(String[] args)
16public static void main(String[] args) {17 System.out.println("Diamond operator:\n");outputDiamond operator: Diamond operator:this.value ← Hello
pass 1 of 47public Box(T valueHello) {8 this.value→ Hello = valueHello;9}All 4 passes — pass 1 is the card above pass valuethis.value1 Hello Hello 2 World World 3 Hello Hello 4 42 42 System.out.println(" Old way: " + box1.getValue());
20Box<String> box1 = new Box<String>("Hello");21System.out.println(" Old way: " + box1.getValue());public T getValue()
pass 1 of 811public T getValue() {12 return valueHello;13}All 8 passes — pass 1 is the card above pass value1 Hello 2 Hello 3 World 4 World 5 Hello 6 Hello 7 42 8 42 System.out.println(" Old way: " + box1.getValue());
20Box<String> box1 = new Box<String>("Hello");21System.out.println(" Old way: " + box1.getValue());output Old way: HelloSystem.out.println(" Old way: " + box1.getValue());
20Box<String> box1 = new Box<String>("Hello");21System.out.println(" Old way: " + box1.getValue());output Old way: HelloSystem.out.println(" Diamond: " + box2.getValue());
24Box<String> box2 = new Box<>("World");25System.out.println(" Diamond: " + box2.getValue());System.out.println(" Diamond: " + box2.getValue());
24Box<String> box2 = new Box<>("World");25System.out.println(" Diamond: " + box2.getValue());output Diamond: WorldSystem.out.println(" List: " + list2);
24Box<String> box2 = new Box<>("World");25System.out.println(" Diamond: " + box2.getValue());2627// Diamond operator <> infers type from left side28// Available since Java 729// Reduces verbosity while maintaining type safety30// Compiler infers the type parameter3132System.out.println("\nWith collections:");3334// Verbose35List<String> list1 = new ArrayList<String>();36list1.add("Apple");3738// Diamond39List<String> list2 = new ArrayList<>();40list2.add("Banana");4142Map<String, Integer> map = new LinkedHashMap<>();43map.put("Alice", 30);44map.put("Bob", 25);4546System.out.println(" List: " + list2[Banana]);47System.out.println(" Map: " + map{Alice=30, Bob=25});4849System.out.println("\nNested generics:");5051// Before Java 7 (very verbose)52Map<String, List<Integer>> map1 = 53 new HashMap<String, List<Integer>>();5455// With diamond (cleaner)56Map<String, List<Integer>> map2 = new LinkedHashMap<>();57map2.put("scores", Arrays.asList(85, 90, 95));58map2.put("ages", Arrays.asList(20, 21, 22));5960System.out.println(" Nested map: " + map2{scores=[85, 90, 95], ages=[20, 21, 22]});6162System.out.println("\nCustom classes:");output Diamond: World With collections: With collections: List: [Banana] List: [Banana] Map: {Alice=30, Bob=25} Map: {Alice=30, Bob=25} Nested generics: Nested generics: Nested map: {scores=[85, 90, 95], ages=[20, 21, 22]} Nested map: {scores=[85, 90, 95], ages=[20, 21, 22]} Custom classes: Custom classes:this.key ← age, this.value ← 30
pass 1 of 268Pair(K keyage, V value30) {69 this.key→ age = keyage;70 this.value→ 30 = value30;71}this.key ← 1, this.value ← first
pass 2 of 268Pair(K key1, V valuefirst) {69 this.key→ 1 = key1;70 this.value→ first = valuefirst;71}System.out.println(" " + pair1);
83System.out.println(" " + pair1age=30);84System.out.println(" " + pair21=first);8586System.out.println("\nReturn type inference:");output age=30 age=30 1=first 1=first Return type inference: Return type inference:static <T> Box<T> createBox(T value)
pass 1 of 288class Factory {89 static <T> Box<T> createBox(T valueHello) {90 return new Box<>(value); // Diamond infers T91 }static <T> Box<T> createBox(T value)
pass 2 of 288class Factory {89 static <T> Box<T> createBox(T value42) {90 return new Box<>(value); // Diamond infers T91 }System.out.println(" String box: " + strBox.getValue());
97System.out.println(" String box: " + strBox.getValue());98System.out.println(" Integer box: " + intBox.getValue());System.out.println(" String box: " + strBox.getValue());
97System.out.println(" String box: " + strBox.getValue());98System.out.println(" Integer box: " + intBox.getValue());output String box: HelloSystem.out.println(" String box: " + strBox.getValue());
97System.out.println(" String box: " + strBox.getValue());98System.out.println(" Integer box: " + intBox.getValue());output String box: HelloSystem.out.println(" Integer box: " + intBox.getValue());
97System.out.println(" String box: " + strBox.getValue());98System.out.println(" Integer box: " + intBox.getValue());output Integer box: 42System.out.println(" Integer box: " + intBox.getValue());
97System.out.println(" String box: " + strBox.getValue());98System.out.println(" Integer box: " + intBox.getValue());99100System.out.println("\nComplex example:");output Integer box: 42 Complex example: Complex example:this.items ← []
pass 1 of 2105Container() {106 this.items→ [] = new ArrayList<>(); // Diamond107}container.add("A");
118Container<String> container = new Container<>(); // Diamond119container.add("A");120container.add("B");void add(T item)
pass 1 of 5109void add(T itemA) {110 items.add(itemA);111}All 5 passes — pass 1 is the card above pass item1 A 2 B 3 C 4 1 5 2 container.add("A");
118Container<String> container = new Container<>(); // Diamond119container.add("A");120container.add("B");121container.add("C");container.add("B");
119container.add("A");120container.add("B");121container.add("C");container.add("C");
120container.add("B");121container.add("C");122123System.out.println(" Items: " + container.getItems());List<T> getItems()
pass 1 of 2113List<T> getItems() {114 return items[A, B, C];115}containers ← []
123System.out.println(" Items: " + container.getItems());124125// Nested126List<Container<Integer>> containers→ [] = new ArrayList<>();127Container<Integer> c1 = new Container<>();128c1.add(1);output Items: [A, B, C]this.items ← []
pass 2 of 2105Container() {106 this.items→ [] = new ArrayList<>(); // Diamond107}c1 ← ⟨DiamondOperator$1Container A⟩
126List<Container<Integer>> containers = new ArrayList<>();127Container<Integer> c1→ ⟨DiamondOperator$1Container A⟩ = new Container<>();128c1.add(1);129c1.add(2);c1.add(1);
127Container<Integer> c1 = new Container<>();128c1.add(1);129c1.add(2);130containers.add(c1);containers.add(c1);
128 c1.add(1);129 c1.add(2);130 containers.add(c1⟨DiamondOperator$1Container A⟩);131 132 System.out.println(" Nested: " + containers.get(0).getItems());133}List<T> getItems()
pass 2 of 2113List<T> getItems() {114 return items[1, 2];115}System.out.println(" Nested: " + containers.get(0).getItems());
132 System.out.println(" Nested: " + containers.get(0).getItems());133}output Nested: [1, 2]
new Box<>() - compiler infers type from variable declaration.
Exercise: Practical.java
Build a type-safe stack using generics