Generics
Type Bounds
Constraining Generics
Your generic method needs to call compareTo(). But T could be anything - the
compiler won't allow it. With <T extends Comparable<T>>, you guarantee T has
compareTo(), and the compiler lets you use it.
Upper bounds with extends
Restrict T to a type or its subtypes.
public class UpperBounds {
static class NumberBox<T extends Number> {
private T value;
public NumberBox(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public double getDoubleValue() {
return value.doubleValue(); // Can call Number methods
}
public boolean isPositive() {
return value.doubleValue() > 0;
}
}
public static void main(String[] args) {
System.out.println("Upper bounds:\n");
NumberBox<Integer> intBox = new NumberBox<>(42);
System.out.println(" Integer: " + intBox.getValue());
System.out.println(" As double: " + intBox.getDoubleValue());
System.out.println(" Positive: " + intBox.isPositive());
NumberBox<Double> doubleBox = new NumberBox<>(3.14);
System.out.println(" Double: " + doubleBox.getValue());
System.out.println(" Positive: " + doubleBox.isPositive());
// NumberBox<String> strBox = new NumberBox<>("text"); // Compile error
// <T extends Type> means T must be Type or subclass/implementer
// Enables calling methods from the bounded type
// Number bound allows: intValue(), doubleValue(), etc.
// Compile error if type doesn't satisfy bound
System.out.println("\nComparable bound:");
class Sorter<T extends Comparable<T>> {
public T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
}
Sorter<Integer> intSorter = new Sorter<>();
System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
Sorter<String> strSorter = new Sorter<>();
System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));
System.out.println("\nStatistics:");
class Stats<T extends Number> {
private java.util.List<T> numbers;
public Stats(java.util.List<T> numbers) {
this.numbers = numbers;
}
public double average() {
double sum = 0;
for (T num : numbers) {
sum += num.doubleValue();
}
return sum / numbers.size();
}
public double sum() {
double total = 0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
}
Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));
System.out.println(" Average: " + intStats.average());
System.out.println(" Sum: " + intStats.sum());
System.out.println("\nRange:");
class Range<T extends Comparable<T>> {
private T min;
private T max;
public Range(T min, T max) {
this.min = min;
this.max = max;
}
public boolean contains(T value) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
public String toString() {
return "[" + min + " - " + max + "]";
}
}
Range<Integer> ageRange = new Range<>(18, 65);
System.out.println(" Range: " + ageRange);
int ageToCheck = 25;
System.out.println(" Contains " + ageToCheck + ": " +
ageRange.contains(ageToCheck));
System.out.println(" Contains 70: " + ageRange.contains(70));
Range<String> nameRange = new Range<>("A", "M");
System.out.println(" Name range: " + nameRange);
System.out.println(" Contains Alice: " + nameRange.contains("Alice"));
System.out.println(" Contains Steve: " + nameRange.contains("Steve"));
}
}
public class UpperBounds {
static class NumberBox<T extends Number> {
private T value;
public NumberBox(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public double getDoubleValue() {
return value.doubleValue(); // Can call Number methods
}
public boolean isPositive() {
return value.doubleValue() > 0;
}
}
public static void main(String[] args) {
System.out.println("Upper bounds:\n");
NumberBox<Integer> intBox = new NumberBox<>(42);
System.out.println(" Integer: " + intBox.getValue());
System.out.println(" As double: " + intBox.getDoubleValue());
System.out.println(" Positive: " + intBox.isPositive());
NumberBox<Double> doubleBox = new NumberBox<>(3.14);
System.out.println(" Double: " + doubleBox.getValue());
System.out.println(" Positive: " + doubleBox.isPositive());
// NumberBox<String> strBox = new NumberBox<>("text"); // Compile error
// <T extends Type> means T must be Type or subclass/implementer
// Enables calling methods from the bounded type
// Number bound allows: intValue(), doubleValue(), etc.
// Compile error if type doesn't satisfy bound
System.out.println("\nComparable bound:");
class Sorter<T extends Comparable<T>> {
public T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
}
Sorter<Integer> intSorter = new Sorter<>();
System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
Sorter<String> strSorter = new Sorter<>();
System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));
System.out.println("\nStatistics:");
class Stats<T extends Number> {
private java.util.List<T> numbers;
public Stats(java.util.List<T> numbers) {
this.numbers = numbers;
}
public double average() {
double sum = 0;
for (T num : numbers) {
sum += num.doubleValue();
}
return sum / numbers.size();
}
public double sum() {
double total = 0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
}
Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));
System.out.println(" Average: " + intStats.average());
System.out.println(" Sum: " + intStats.sum());
System.out.println("\nRange:");
class Range<T extends Comparable<T>> {
private T min;
private T max;
public Range(T min, T max) {
this.min = min;
this.max = max;
}
public boolean contains(T value) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
public String toString() {
return "[" + min + " - " + max + "]";
}
}
Range<Integer> ageRange = new Range<>(18, 65);
System.out.println(" Range: " + ageRange);
int ageToCheck = 17;
System.out.println(" Contains " + ageToCheck + ": " +
ageRange.contains(ageToCheck));
System.out.println(" Contains 70: " + ageRange.contains(70));
Range<String> nameRange = new Range<>("A", "M");
System.out.println(" Name range: " + nameRange);
System.out.println(" Contains Alice: " + nameRange.contains("Alice"));
System.out.println(" Contains Steve: " + nameRange.contains("Steve"));
}
}
public class UpperBounds {
static class NumberBox<T extends Number> {
private T value;
public NumberBox(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public double getDoubleValue() {
return value.doubleValue(); // Can call Number methods
}
public boolean isPositive() {
return value.doubleValue() > 0;
}
}
public static void main(String[] args) {
System.out.println("Upper bounds:\n");
NumberBox<Integer> intBox = new NumberBox<>(42);
System.out.println(" Integer: " + intBox.getValue());
System.out.println(" As double: " + intBox.getDoubleValue());
System.out.println(" Positive: " + intBox.isPositive());
NumberBox<Double> doubleBox = new NumberBox<>(3.14);
System.out.println(" Double: " + doubleBox.getValue());
System.out.println(" Positive: " + doubleBox.isPositive());
// NumberBox<String> strBox = new NumberBox<>("text"); // Compile error
// <T extends Type> means T must be Type or subclass/implementer
// Enables calling methods from the bounded type
// Number bound allows: intValue(), doubleValue(), etc.
// Compile error if type doesn't satisfy bound
System.out.println("\nComparable bound:");
class Sorter<T extends Comparable<T>> {
public T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
}
Sorter<Integer> intSorter = new Sorter<>();
System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
Sorter<String> strSorter = new Sorter<>();
System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));
System.out.println("\nStatistics:");
class Stats<T extends Number> {
private java.util.List<T> numbers;
public Stats(java.util.List<T> numbers) {
this.numbers = numbers;
}
public double average() {
double sum = 0;
for (T num : numbers) {
sum += num.doubleValue();
}
return sum / numbers.size();
}
public double sum() {
double total = 0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
}
Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));
System.out.println(" Average: " + intStats.average());
System.out.println(" Sum: " + intStats.sum());
System.out.println("\nRange:");
class Range<T extends Comparable<T>> {
private T min;
private T max;
public Range(T min, T max) {
this.min = min;
this.max = max;
}
public boolean contains(T value) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
public String toString() {
return "[" + min + " - " + max + "]";
}
}
Range<Integer> ageRange = new Range<>(18, 65);
System.out.println(" Range: " + ageRange);
int ageToCheck = 70;
System.out.println(" Contains " + ageToCheck + ": " +
ageRange.contains(ageToCheck));
System.out.println(" Contains 70: " + ageRange.contains(70));
Range<String> nameRange = new Range<>("A", "M");
System.out.println(" Name range: " + nameRange);
System.out.println(" Contains Alice: " + nameRange.contains("Alice"));
System.out.println(" Contains Steve: " + nameRange.contains("Steve"));
}
}
public static void main(String[] args)
22public static void main(String[] args) {23 System.out.println("Upper bounds:\n");outputUpper bounds: Upper bounds:this.value ← 42
pass 1 of 25public NumberBox(T value42) {6 this.value→ 42 = value42;7}System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());public T getValue()
pass 1 of 49public T getValue() {10 return value42;11}All 4 passes — pass 1 is the card above pass value1 42 2 42 3 3.14 4 3.14 System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());output Integer: 42System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Integer: 42System.out.println(" As double: " + intBox.getDoubleValue());
26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output As double: 42.0System.out.println(" As double: " + intBox.getDoubleValue());
26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output As double: 42.0System.out.println(" Positive: " + intBox.isPositive());
27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Positive: trueSystem.out.println(" Positive: " + intBox.isPositive());
27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Positive: truethis.value ← 3.14
pass 2 of 25public NumberBox(T value3.14) {6 this.value→ 3.14 = value3.14;7}System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Double: 3.14System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Double: 3.14System.out.println(" Positive: " + doubleBox.isPositive());
31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Positive: trueSystem.out.println(" Positive: " + doubleBox.isPositive());
31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());3334// NumberBox<String> strBox = new NumberBox<>("text"); // Compile error3536// <T extends Type> means T must be Type or subclass/implementer37// Enables calling methods from the bounded type38// Number bound allows: intValue(), doubleValue(), etc.39// Compile error if type doesn't satisfy bound4041System.out.println("\nComparable bound:");4243class Sorter<T extends Comparable<T>> {44 public T max(T a, T b) {45 return a.compareTo(b) > 0 ? a : b;46 }47 48 public T min(T a, T b) {49 return a.compareTo(b) < 0 ? a : b;50 }51}5253Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Positive: true Comparable bound: Comparable bound:public T max(T a, T b)
pass 1 of 443class Sorter<T extends Comparable<T>> {44 public T max(T a5, T b10) {45 return a.compareTo(b10) > 0 ? a5 : b;46 }All 4 passes — pass 1 is the card above pass ab1 5 10 2 5 10 3 apple banana 4 apple banana System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
53Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Max(5, 10): 10System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
53Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Max(5, 10): 10public T min(T a, T b)
pass 1 of 248public T min(T a5, T b10) {49 return a.compareTo(b10) < 0 ? a5 : b;50}System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Min(5, 10): 5public T min(T a, T b)
pass 2 of 248public T min(T a5, T b10) {49 return a.compareTo(b10) < 0 ? a5 : b;50}System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));5657Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));output Min(5, 10): 5System.out.println(" Max(apple, banana): " + strSorter.max("apple", "…
57Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));output Max(apple, banana): bananaSystem.out.println(" Max(apple, banana): " + strSorter.max("apple", "…
57Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));5960System.out.println("\nStatistics:");output Max(apple, banana): banana Statistics: Statistics:this.numbers ← [10, 20, 30, 40]
65public Stats(java.util.List<T> numbers[10, 20, 30, 40]) {66 this.numbers→ [10, 20, 30, 40] = numbers[10, 20, 30, 40];67}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());sum ← 0.0
pass 1 of 269public double average() {70 double sum→ 0.0 = 0;71 for (T num : numbers) {sum ← 10.0
pass 1 of 870double sum = 0;71for (T num10 : numbers[10, 20, 30, 40]) {72 sum→ 10.0 += num.doubleValue();73}All 8 passes — pass 1 is the card above pass numsum1 10 0.0 → 10.0 2 20 10.0 → 30.0 3 30 30.0 → 60.0 4 40 60.0 → 100.0 5 10 0.0 → 10.0 6 20 10.0 → 30.0 7 30 30.0 → 60.0 8 40 60.0 → 100.0 return sum / numbers.size();
73 }74 return sum100.0 / numbers.size();75}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Average: 25.0sum ← 0.0
pass 2 of 269public double average() {70 double sum→ 0.0 = 0;71 for (T num : numbers) {return sum / numbers.size();
73 }74 return sum100.0 / numbers.size();75}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Average: 25.0total ← 0.0
pass 1 of 277public double sum() {78 double total→ 0.0 = 0;79 for (T num : numbers) {total ← 10.0
pass 1 of 878double total = 0;79for (T num10 : numbers[10, 20, 30, 40]) {80 total→ 10.0 += num.doubleValue();81}All 8 passes — pass 1 is the card above pass numtotal1 10 0.0 → 10.0 2 20 10.0 → 30.0 3 30 30.0 → 60.0 4 40 60.0 → 100.0 5 10 0.0 → 10.0 6 20 10.0 → 30.0 7 30 30.0 → 60.0 8 40 60.0 → 100.0 return total;
81 }82 return total100.0;83}System.out.println(" Sum: " + intStats.sum());
87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Sum: 100.0total ← 0.0
pass 2 of 277public double sum() {78 double total→ 0.0 = 0;79 for (T num : numbers) {return total;
81 }82 return total100.0;83}System.out.println(" Sum: " + intStats.sum());
87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());8990System.out.println("\nRange:");output Sum: 100.0 Range: Range:this.min ← 18, this.max ← 65
pass 1 of 296public Range(T min18, T max65) {97 this.min→ 18 = min18;98 this.max→ 65 = max65;99}ageToCheck ← 25
110Range<Integer> ageRange = new Range<>(18, 65);111System.out.println(" Range: " + ageRange[18 - 65]);112int ageToCheck→ 25 = 25; //@ageToCheck=25, 17, 70113System.out.println(" Contains " + ageToCheck25 + ": " +114 ageRange.contains(ageToCheck25));115System.out.println(" Contains 70: " + ageRange.contains(70));output Range: [18 - 65]public boolean contains(T value)
pass 1 of 4101public boolean contains(T value25) {102 return value.compareTo(min18) >= 0 && value.compareTo(max65) <= 0;103}All 4 passes — pass 1 is the card above pass valueminmax1 25 18 65 2 70 18 65 3 Alice A M 4 Steve A M System.out.println(" Contains " + ageToCheck + ": " +
112int ageToCheck = 25; //@ageToCheck=25, 17, 70113System.out.println(" Contains " + ageToCheck25 + ": " +114 ageRange.contains(ageToCheck25));115System.out.println(" Contains 70: " + ageRange.contains(70));output Contains 25: trueSystem.out.println(" Contains 70: " + ageRange.contains(70));
114 ageRange.contains(ageToCheck));115System.out.println(" Contains 70: " + ageRange.contains(70));116117Range<String> nameRange = new Range<>("A", "M");118System.out.println(" Name range: " + nameRange);output Contains 70: falsethis.min ← A, this.max ← M
pass 2 of 296public Range(T minA, T maxM) {97 this.min→ A = minA;98 this.max→ M = maxM;99}nameRange ← [A - M]
117Range<String> nameRange→ [A - M] = new Range<>("A", "M");118System.out.println(" Name range: " + nameRange[A - M]);119System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120System.out.println(" Contains Steve: " + nameRange.contains("Steve"));output Name range: [A - M]System.out.println(" Contains Alice: " + nameRange.contains("Alice"))…
118 System.out.println(" Name range: " + nameRange);119 System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120 System.out.println(" Contains Steve: " + nameRange.contains("Steve"));121}output Contains Alice: trueSystem.out.println(" Contains Steve: " + nameRange.contains("Steve"))…
119 System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120 System.out.println(" Contains Steve: " + nameRange.contains("Steve"));121}output Contains Steve: false
public static void main(String[] args)
22public static void main(String[] args) {23 System.out.println("Upper bounds:\n");outputUpper bounds: Upper bounds:this.value ← 42
pass 1 of 25public NumberBox(T value42) {6 this.value→ 42 = value42;7}System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());public T getValue()
pass 1 of 49public T getValue() {10 return value42;11}All 4 passes — pass 1 is the card above pass value1 42 2 42 3 3.14 4 3.14 System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());output Integer: 42System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Integer: 42System.out.println(" As double: " + intBox.getDoubleValue());
26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output As double: 42.0System.out.println(" As double: " + intBox.getDoubleValue());
26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output As double: 42.0System.out.println(" Positive: " + intBox.isPositive());
27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Positive: trueSystem.out.println(" Positive: " + intBox.isPositive());
27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Positive: truethis.value ← 3.14
pass 2 of 25public NumberBox(T value3.14) {6 this.value→ 3.14 = value3.14;7}System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Double: 3.14System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Double: 3.14System.out.println(" Positive: " + doubleBox.isPositive());
31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Positive: trueSystem.out.println(" Positive: " + doubleBox.isPositive());
31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());3334// NumberBox<String> strBox = new NumberBox<>("text"); // Compile error3536// <T extends Type> means T must be Type or subclass/implementer37// Enables calling methods from the bounded type38// Number bound allows: intValue(), doubleValue(), etc.39// Compile error if type doesn't satisfy bound4041System.out.println("\nComparable bound:");4243class Sorter<T extends Comparable<T>> {44 public T max(T a, T b) {45 return a.compareTo(b) > 0 ? a : b;46 }47 48 public T min(T a, T b) {49 return a.compareTo(b) < 0 ? a : b;50 }51}5253Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Positive: true Comparable bound: Comparable bound:public T max(T a, T b)
pass 1 of 443class Sorter<T extends Comparable<T>> {44 public T max(T a5, T b10) {45 return a.compareTo(b10) > 0 ? a5 : b;46 }All 4 passes — pass 1 is the card above pass ab1 5 10 2 5 10 3 apple banana 4 apple banana System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
53Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Max(5, 10): 10System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
53Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Max(5, 10): 10public T min(T a, T b)
pass 1 of 248public T min(T a5, T b10) {49 return a.compareTo(b10) < 0 ? a5 : b;50}System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Min(5, 10): 5public T min(T a, T b)
pass 2 of 248public T min(T a5, T b10) {49 return a.compareTo(b10) < 0 ? a5 : b;50}System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));5657Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));output Min(5, 10): 5System.out.println(" Max(apple, banana): " + strSorter.max("apple", "…
57Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));output Max(apple, banana): bananaSystem.out.println(" Max(apple, banana): " + strSorter.max("apple", "…
57Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));5960System.out.println("\nStatistics:");output Max(apple, banana): banana Statistics: Statistics:this.numbers ← [10, 20, 30, 40]
65public Stats(java.util.List<T> numbers[10, 20, 30, 40]) {66 this.numbers→ [10, 20, 30, 40] = numbers[10, 20, 30, 40];67}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());sum ← 0.0
pass 1 of 269public double average() {70 double sum→ 0.0 = 0;71 for (T num : numbers) {sum ← 10.0
pass 1 of 870double sum = 0;71for (T num10 : numbers[10, 20, 30, 40]) {72 sum→ 10.0 += num.doubleValue();73}All 8 passes — pass 1 is the card above pass numsum1 10 0.0 → 10.0 2 20 10.0 → 30.0 3 30 30.0 → 60.0 4 40 60.0 → 100.0 5 10 0.0 → 10.0 6 20 10.0 → 30.0 7 30 30.0 → 60.0 8 40 60.0 → 100.0 return sum / numbers.size();
73 }74 return sum100.0 / numbers.size();75}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Average: 25.0sum ← 0.0
pass 2 of 269public double average() {70 double sum→ 0.0 = 0;71 for (T num : numbers) {return sum / numbers.size();
73 }74 return sum100.0 / numbers.size();75}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Average: 25.0total ← 0.0
pass 1 of 277public double sum() {78 double total→ 0.0 = 0;79 for (T num : numbers) {total ← 10.0
pass 1 of 878double total = 0;79for (T num10 : numbers[10, 20, 30, 40]) {80 total→ 10.0 += num.doubleValue();81}All 8 passes — pass 1 is the card above pass numtotal1 10 0.0 → 10.0 2 20 10.0 → 30.0 3 30 30.0 → 60.0 4 40 60.0 → 100.0 5 10 0.0 → 10.0 6 20 10.0 → 30.0 7 30 30.0 → 60.0 8 40 60.0 → 100.0 return total;
81 }82 return total100.0;83}System.out.println(" Sum: " + intStats.sum());
87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Sum: 100.0total ← 0.0
pass 2 of 277public double sum() {78 double total→ 0.0 = 0;79 for (T num : numbers) {return total;
81 }82 return total100.0;83}System.out.println(" Sum: " + intStats.sum());
87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());8990System.out.println("\nRange:");output Sum: 100.0 Range: Range:this.min ← 18, this.max ← 65
pass 1 of 296public Range(T min18, T max65) {97 this.min→ 18 = min18;98 this.max→ 65 = max65;99}ageToCheck ← 17
110Range<Integer> ageRange = new Range<>(18, 65);111System.out.println(" Range: " + ageRange[18 - 65]);112int ageToCheck→ 17 = 17;113System.out.println(" Contains " + ageToCheck17 + ": " +114 ageRange.contains(ageToCheck17));115System.out.println(" Contains 70: " + ageRange.contains(70));output Range: [18 - 65]public boolean contains(T value)
pass 1 of 4101public boolean contains(T value17) {102 return value.compareTo(min18) >= 0 && value.compareTo(max65) <= 0;103}All 4 passes — pass 1 is the card above pass valueminmax1 17 18 65 2 70 18 65 3 Alice A M 4 Steve A M System.out.println(" Contains " + ageToCheck + ": " +
112int ageToCheck = 17;113System.out.println(" Contains " + ageToCheck17 + ": " +114 ageRange.contains(ageToCheck17));115System.out.println(" Contains 70: " + ageRange.contains(70));output Contains 17: falseSystem.out.println(" Contains 70: " + ageRange.contains(70));
114 ageRange.contains(ageToCheck));115System.out.println(" Contains 70: " + ageRange.contains(70));116117Range<String> nameRange = new Range<>("A", "M");118System.out.println(" Name range: " + nameRange);output Contains 70: falsethis.min ← A, this.max ← M
pass 2 of 296public Range(T minA, T maxM) {97 this.min→ A = minA;98 this.max→ M = maxM;99}nameRange ← [A - M]
117Range<String> nameRange→ [A - M] = new Range<>("A", "M");118System.out.println(" Name range: " + nameRange[A - M]);119System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120System.out.println(" Contains Steve: " + nameRange.contains("Steve"));output Name range: [A - M]System.out.println(" Contains Alice: " + nameRange.contains("Alice"))…
118 System.out.println(" Name range: " + nameRange);119 System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120 System.out.println(" Contains Steve: " + nameRange.contains("Steve"));121}output Contains Alice: trueSystem.out.println(" Contains Steve: " + nameRange.contains("Steve"))…
119 System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120 System.out.println(" Contains Steve: " + nameRange.contains("Steve"));121}output Contains Steve: false
public static void main(String[] args)
22public static void main(String[] args) {23 System.out.println("Upper bounds:\n");outputUpper bounds: Upper bounds:this.value ← 42
pass 1 of 25public NumberBox(T value42) {6 this.value→ 42 = value42;7}System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());public T getValue()
pass 1 of 49public T getValue() {10 return value42;11}All 4 passes — pass 1 is the card above pass value1 42 2 42 3 3.14 4 3.14 System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());output Integer: 42System.out.println(" Integer: " + intBox.getValue());
25NumberBox<Integer> intBox = new NumberBox<>(42);26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Integer: 42System.out.println(" As double: " + intBox.getDoubleValue());
26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output As double: 42.0System.out.println(" As double: " + intBox.getDoubleValue());
26System.out.println(" Integer: " + intBox.getValue());27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output As double: 42.0System.out.println(" Positive: " + intBox.isPositive());
27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Positive: trueSystem.out.println(" Positive: " + intBox.isPositive());
27System.out.println(" As double: " + intBox.getDoubleValue());28System.out.println(" Positive: " + intBox.isPositive());output Positive: truethis.value ← 3.14
pass 2 of 25public NumberBox(T value3.14) {6 this.value→ 3.14 = value3.14;7}System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Double: 3.14System.out.println(" Double: " + doubleBox.getValue());
30NumberBox<Double> doubleBox = new NumberBox<>(3.14);31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Double: 3.14System.out.println(" Positive: " + doubleBox.isPositive());
31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());output Positive: trueSystem.out.println(" Positive: " + doubleBox.isPositive());
31System.out.println(" Double: " + doubleBox.getValue());32System.out.println(" Positive: " + doubleBox.isPositive());3334// NumberBox<String> strBox = new NumberBox<>("text"); // Compile error3536// <T extends Type> means T must be Type or subclass/implementer37// Enables calling methods from the bounded type38// Number bound allows: intValue(), doubleValue(), etc.39// Compile error if type doesn't satisfy bound4041System.out.println("\nComparable bound:");4243class Sorter<T extends Comparable<T>> {44 public T max(T a, T b) {45 return a.compareTo(b) > 0 ? a : b;46 }47 48 public T min(T a, T b) {49 return a.compareTo(b) < 0 ? a : b;50 }51}5253Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Positive: true Comparable bound: Comparable bound:public T max(T a, T b)
pass 1 of 443class Sorter<T extends Comparable<T>> {44 public T max(T a5, T b10) {45 return a.compareTo(b10) > 0 ? a5 : b;46 }All 4 passes — pass 1 is the card above pass ab1 5 10 2 5 10 3 apple banana 4 apple banana System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
53Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Max(5, 10): 10System.out.println(" Max(5, 10): " + intSorter.max(5, 10));
53Sorter<Integer> intSorter = new Sorter<>();54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Max(5, 10): 10public T min(T a, T b)
pass 1 of 248public T min(T a5, T b10) {49 return a.compareTo(b10) < 0 ? a5 : b;50}System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));output Min(5, 10): 5public T min(T a, T b)
pass 2 of 248public T min(T a5, T b10) {49 return a.compareTo(b10) < 0 ? a5 : b;50}System.out.println(" Min(5, 10): " + intSorter.min(5, 10));
54System.out.println(" Max(5, 10): " + intSorter.max(5, 10));55System.out.println(" Min(5, 10): " + intSorter.min(5, 10));5657Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));output Min(5, 10): 5System.out.println(" Max(apple, banana): " + strSorter.max("apple", "…
57Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));output Max(apple, banana): bananaSystem.out.println(" Max(apple, banana): " + strSorter.max("apple", "…
57Sorter<String> strSorter = new Sorter<>();58System.out.println(" Max(apple, banana): " + strSorter.max("apple", "banana"));5960System.out.println("\nStatistics:");output Max(apple, banana): banana Statistics: Statistics:this.numbers ← [10, 20, 30, 40]
65public Stats(java.util.List<T> numbers[10, 20, 30, 40]) {66 this.numbers→ [10, 20, 30, 40] = numbers[10, 20, 30, 40];67}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());sum ← 0.0
pass 1 of 269public double average() {70 double sum→ 0.0 = 0;71 for (T num : numbers) {sum ← 10.0
pass 1 of 870double sum = 0;71for (T num10 : numbers[10, 20, 30, 40]) {72 sum→ 10.0 += num.doubleValue();73}All 8 passes — pass 1 is the card above pass numsum1 10 0.0 → 10.0 2 20 10.0 → 30.0 3 30 30.0 → 60.0 4 40 60.0 → 100.0 5 10 0.0 → 10.0 6 20 10.0 → 30.0 7 30 30.0 → 60.0 8 40 60.0 → 100.0 return sum / numbers.size();
73 }74 return sum100.0 / numbers.size();75}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Average: 25.0sum ← 0.0
pass 2 of 269public double average() {70 double sum→ 0.0 = 0;71 for (T num : numbers) {return sum / numbers.size();
73 }74 return sum100.0 / numbers.size();75}System.out.println(" Average: " + intStats.average());
86Stats<Integer> intStats = new Stats<>(java.util.Arrays.asList(10, 20, 30, 40));87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Average: 25.0total ← 0.0
pass 1 of 277public double sum() {78 double total→ 0.0 = 0;79 for (T num : numbers) {total ← 10.0
pass 1 of 878double total = 0;79for (T num10 : numbers[10, 20, 30, 40]) {80 total→ 10.0 += num.doubleValue();81}All 8 passes — pass 1 is the card above pass numtotal1 10 0.0 → 10.0 2 20 10.0 → 30.0 3 30 30.0 → 60.0 4 40 60.0 → 100.0 5 10 0.0 → 10.0 6 20 10.0 → 30.0 7 30 30.0 → 60.0 8 40 60.0 → 100.0 return total;
81 }82 return total100.0;83}System.out.println(" Sum: " + intStats.sum());
87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());output Sum: 100.0total ← 0.0
pass 2 of 277public double sum() {78 double total→ 0.0 = 0;79 for (T num : numbers) {return total;
81 }82 return total100.0;83}System.out.println(" Sum: " + intStats.sum());
87System.out.println(" Average: " + intStats.average());88System.out.println(" Sum: " + intStats.sum());8990System.out.println("\nRange:");output Sum: 100.0 Range: Range:this.min ← 18, this.max ← 65
pass 1 of 296public Range(T min18, T max65) {97 this.min→ 18 = min18;98 this.max→ 65 = max65;99}ageToCheck ← 70
110Range<Integer> ageRange = new Range<>(18, 65);111System.out.println(" Range: " + ageRange[18 - 65]);112int ageToCheck→ 70 = 70;113System.out.println(" Contains " + ageToCheck70 + ": " +114 ageRange.contains(ageToCheck70));115System.out.println(" Contains 70: " + ageRange.contains(70));output Range: [18 - 65]public boolean contains(T value)
pass 1 of 4101public boolean contains(T value70) {102 return value.compareTo(min18) >= 0 && value.compareTo(max65) <= 0;103}All 4 passes — pass 1 is the card above pass valueminmax1 70 18 65 2 70 18 65 3 Alice A M 4 Steve A M System.out.println(" Contains " + ageToCheck + ": " +
112int ageToCheck = 70;113System.out.println(" Contains " + ageToCheck70 + ": " +114 ageRange.contains(ageToCheck70));115System.out.println(" Contains 70: " + ageRange.contains(70));output Contains 70: falseSystem.out.println(" Contains 70: " + ageRange.contains(70));
114 ageRange.contains(ageToCheck));115System.out.println(" Contains 70: " + ageRange.contains(70));116117Range<String> nameRange = new Range<>("A", "M");118System.out.println(" Name range: " + nameRange);output Contains 70: falsethis.min ← A, this.max ← M
pass 2 of 296public Range(T minA, T maxM) {97 this.min→ A = minA;98 this.max→ M = maxM;99}nameRange ← [A - M]
117Range<String> nameRange→ [A - M] = new Range<>("A", "M");118System.out.println(" Name range: " + nameRange[A - M]);119System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120System.out.println(" Contains Steve: " + nameRange.contains("Steve"));output Name range: [A - M]System.out.println(" Contains Alice: " + nameRange.contains("Alice"))…
118 System.out.println(" Name range: " + nameRange);119 System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120 System.out.println(" Contains Steve: " + nameRange.contains("Steve"));121}output Contains Alice: trueSystem.out.println(" Contains Steve: " + nameRange.contains("Steve"))…
119 System.out.println(" Contains Alice: " + nameRange.contains("Alice"));120 System.out.println(" Contains Steve: " + nameRange.contains("Steve"));121}output Contains Steve: false
<T extends Number> - T must be Number or subclass. Can call Number methods.
Multiple bounds
Combine class and interface constraints.
import java.io.Serializable;
public class MultipleBounds {
static class Calculator<T extends Number & Comparable<T>> {
public T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public double add(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
public boolean inRange(T value, T min, T max) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
}
public static void main(String[] args) {
System.out.println("Multiple bounds:\n");
Calculator<Integer> intCalc = new Calculator<>();
System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
System.out.println(" Add(5, 10): " + intCalc.add(5, 10));
int rangeValue = 7;
System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
intCalc.inRange(rangeValue, 5, 10));
Calculator<Double> doubleCalc = new Calculator<>();
System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));
// Multiple bounds: <T extends Type1 & Type2 & Type3>
// Class bound must come first (can only have one class)
// Interface bounds follow, separated by &
// T must satisfy ALL bounds
System.out.println("\nSerializable + Comparable:");
class Storage<T extends Serializable & Comparable<T>> {
private T value;
public void store(T value) {
this.value = value;
System.out.println(" Stored (serializable): " + value);
}
public T retrieve() {
return value;
}
public boolean isGreaterThan(T other) {
return value != null && value.compareTo(other) > 0;
}
}
Storage<String> strStorage = new Storage<>();
strStorage.store("Hello");
System.out.println(" Greater than 'Apple': " +
strStorage.isGreaterThan("Apple"));
Storage<Integer> intStorage = new Storage<>();
intStorage.store(42);
System.out.println(" Greater than 30: " +
intStorage.isGreaterThan(30));
System.out.println("\nCustom interfaces:");
interface Nameable {
String getName();
}
interface Identifiable {
long getId();
}
class Entity<T extends Nameable & Identifiable> {
private T item;
public Entity(T item) {
this.item = item;
}
public void display() {
System.out.println(" ID: " + item.getId() +
", Name: " + item.getName());
}
}
class User implements Nameable, Identifiable {
private long id;
private String name;
User(long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getName() { return name; }
@Override
public long getId() { return id; }
}
Entity<User> userEntity = new Entity<>(new User(1, "Alice"));
userEntity.display();
System.out.println("\nThree bounds:");
interface Readable {
String read();
}
interface Writable {
void write(String data);
}
interface Closeable {
void close();
}
class Resource<T extends Readable & Writable & Closeable> {
private T resource;
public Resource(T resource) {
this.resource = resource;
}
public void process() {
String data = resource.read();
System.out.println(" Read: " + data);
resource.write("Processed: " + data);
resource.close();
}
}
class File implements Readable, Writable, Closeable {
private String content = "File content";
@Override
public String read() { return content; }
@Override
public void write(String data) {
System.out.println(" Writing: " + data);
}
@Override
public void close() {
System.out.println(" Closed");
}
}
Resource<File> fileResource = new Resource<>(new File());
fileResource.process();
}
}
import java.io.Serializable;
public class MultipleBounds {
static class Calculator<T extends Number & Comparable<T>> {
public T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public double add(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
public boolean inRange(T value, T min, T max) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
}
public static void main(String[] args) {
System.out.println("Multiple bounds:\n");
Calculator<Integer> intCalc = new Calculator<>();
System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
System.out.println(" Add(5, 10): " + intCalc.add(5, 10));
int rangeValue = 4;
System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
intCalc.inRange(rangeValue, 5, 10));
Calculator<Double> doubleCalc = new Calculator<>();
System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));
// Multiple bounds: <T extends Type1 & Type2 & Type3>
// Class bound must come first (can only have one class)
// Interface bounds follow, separated by &
// T must satisfy ALL bounds
System.out.println("\nSerializable + Comparable:");
class Storage<T extends Serializable & Comparable<T>> {
private T value;
public void store(T value) {
this.value = value;
System.out.println(" Stored (serializable): " + value);
}
public T retrieve() {
return value;
}
public boolean isGreaterThan(T other) {
return value != null && value.compareTo(other) > 0;
}
}
Storage<String> strStorage = new Storage<>();
strStorage.store("Hello");
System.out.println(" Greater than 'Apple': " +
strStorage.isGreaterThan("Apple"));
Storage<Integer> intStorage = new Storage<>();
intStorage.store(42);
System.out.println(" Greater than 30: " +
intStorage.isGreaterThan(30));
System.out.println("\nCustom interfaces:");
interface Nameable {
String getName();
}
interface Identifiable {
long getId();
}
class Entity<T extends Nameable & Identifiable> {
private T item;
public Entity(T item) {
this.item = item;
}
public void display() {
System.out.println(" ID: " + item.getId() +
", Name: " + item.getName());
}
}
class User implements Nameable, Identifiable {
private long id;
private String name;
User(long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getName() { return name; }
@Override
public long getId() { return id; }
}
Entity<User> userEntity = new Entity<>(new User(1, "Alice"));
userEntity.display();
System.out.println("\nThree bounds:");
interface Readable {
String read();
}
interface Writable {
void write(String data);
}
interface Closeable {
void close();
}
class Resource<T extends Readable & Writable & Closeable> {
private T resource;
public Resource(T resource) {
this.resource = resource;
}
public void process() {
String data = resource.read();
System.out.println(" Read: " + data);
resource.write("Processed: " + data);
resource.close();
}
}
class File implements Readable, Writable, Closeable {
private String content = "File content";
@Override
public String read() { return content; }
@Override
public void write(String data) {
System.out.println(" Writing: " + data);
}
@Override
public void close() {
System.out.println(" Closed");
}
}
Resource<File> fileResource = new Resource<>(new File());
fileResource.process();
}
}
import java.io.Serializable;
public class MultipleBounds {
static class Calculator<T extends Number & Comparable<T>> {
public T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public double add(T a, T b) {
return a.doubleValue() + b.doubleValue();
}
public boolean inRange(T value, T min, T max) {
return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
}
}
public static void main(String[] args) {
System.out.println("Multiple bounds:\n");
Calculator<Integer> intCalc = new Calculator<>();
System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
System.out.println(" Add(5, 10): " + intCalc.add(5, 10));
int rangeValue = 12;
System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
intCalc.inRange(rangeValue, 5, 10));
Calculator<Double> doubleCalc = new Calculator<>();
System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));
// Multiple bounds: <T extends Type1 & Type2 & Type3>
// Class bound must come first (can only have one class)
// Interface bounds follow, separated by &
// T must satisfy ALL bounds
System.out.println("\nSerializable + Comparable:");
class Storage<T extends Serializable & Comparable<T>> {
private T value;
public void store(T value) {
this.value = value;
System.out.println(" Stored (serializable): " + value);
}
public T retrieve() {
return value;
}
public boolean isGreaterThan(T other) {
return value != null && value.compareTo(other) > 0;
}
}
Storage<String> strStorage = new Storage<>();
strStorage.store("Hello");
System.out.println(" Greater than 'Apple': " +
strStorage.isGreaterThan("Apple"));
Storage<Integer> intStorage = new Storage<>();
intStorage.store(42);
System.out.println(" Greater than 30: " +
intStorage.isGreaterThan(30));
System.out.println("\nCustom interfaces:");
interface Nameable {
String getName();
}
interface Identifiable {
long getId();
}
class Entity<T extends Nameable & Identifiable> {
private T item;
public Entity(T item) {
this.item = item;
}
public void display() {
System.out.println(" ID: " + item.getId() +
", Name: " + item.getName());
}
}
class User implements Nameable, Identifiable {
private long id;
private String name;
User(long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getName() { return name; }
@Override
public long getId() { return id; }
}
Entity<User> userEntity = new Entity<>(new User(1, "Alice"));
userEntity.display();
System.out.println("\nThree bounds:");
interface Readable {
String read();
}
interface Writable {
void write(String data);
}
interface Closeable {
void close();
}
class Resource<T extends Readable & Writable & Closeable> {
private T resource;
public Resource(T resource) {
this.resource = resource;
}
public void process() {
String data = resource.read();
System.out.println(" Read: " + data);
resource.write("Processed: " + data);
resource.close();
}
}
class File implements Readable, Writable, Closeable {
private String content = "File content";
@Override
public String read() { return content; }
@Override
public void write(String data) {
System.out.println(" Writing: " + data);
}
@Override
public void close() {
System.out.println(" Closed");
}
}
Resource<File> fileResource = new Resource<>(new File());
fileResource.process();
}
}
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Multiple bounds:\n");20 21 Calculator<Integer> intCalc = new Calculator<>();22 System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23 System.out.println(" Add(5, 10): " + intCalc.add(5, 10));outputMultiple bounds: Multiple bounds:public T max(T a, T b)
pass 1 of 44static class Calculator<T extends Number & Comparable<T>> {5 public T max(T a5, T b10) {6 return a.compareTo(b10) > 0 ? a5 : b;7 }All 4 passes — pass 1 is the card above pass ab1 5 10 2 5 10 3 3.14 2.71 4 3.14 2.71 System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
21Calculator<Integer> intCalc = new Calculator<>();22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));output Max(5, 10): 10System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
21Calculator<Integer> intCalc = new Calculator<>();22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 7; //@rangeValue=7, 4, 12output Max(5, 10): 10public double add(T a, T b)
pass 1 of 29public double add(T a5, T b10) {10 return a.doubleValue() + b.doubleValue();11}System.out.println(" Add(5, 10): " + intCalc.add(5, 10));
22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 7; //@rangeValue=7, 4, 12output Add(5, 10): 15.0public double add(T a, T b)
pass 2 of 29public double add(T a5, T b10) {10 return a.doubleValue() + b.doubleValue();11}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 7; //@rangeValue=7, 4, 1225System.out.println(" InRange(" + rangeValue7 + ", 5, 10): " +26 intCalc.inRange(rangeValue7, 5, 10));output Add(5, 10): 15.0public boolean inRange(T value, T min, T max)
pass 1 of 213public boolean inRange(T value7, T min5, T max10) {14 return value.compareTo(min5) >= 0 && value.compareTo(max10) <= 0;15}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
24int rangeValue = 7; //@rangeValue=7, 4, 1225System.out.println(" InRange(" + rangeValue7 + ", 5, 10): " +26 intCalc.inRange(rangeValue7, 5, 10));output InRange(7, 5, 10): truepublic boolean inRange(T value, T min, T max)
pass 2 of 213public boolean inRange(T value7, T min5, T max10) {14 return value.compareTo(min5) >= 0 && value.compareTo(max10) <= 0;15}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
24int rangeValue = 7; //@rangeValue=7, 4, 1225System.out.println(" InRange(" + rangeValue7 + ", 5, 10): " +26 intCalc.inRange(rangeValue7, 5, 10));2728Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));output InRange(7, 5, 10): trueSystem.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71))…
28Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));output Max(3.14, 2.71): 3.14System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71))…
28Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));3031// Multiple bounds: <T extends Type1 & Type2 & Type3>32// Class bound must come first (can only have one class)33// Interface bounds follow, separated by &34// T must satisfy ALL bounds3536System.out.println("\nSerializable + Comparable:");3738class Storage<T extends Serializable & Comparable<T>> {39 private T value;40 41 public void store(T value) {42 this.value = value;43 System.out.println(" Stored (serializable): " + value);44 }45 46 public T retrieve() {47 return value;48 }49 50 public boolean isGreaterThan(T other) {51 return value != null && value.compareTo(other) > 0;52 }53}5455Storage<String> strStorage = new Storage<>();56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " +output Max(3.14, 2.71): 3.14 Serializable + Comparable: Serializable + Comparable:this.value ← Hello
pass 1 of 241public void store(T valueHello) {42 this.value→ Hello = valueHello;43 System.out.println(" Stored (serializable): " + valueHello);44}output Stored (serializable): HellostrStorage.store("Hello");
55Storage<String> strStorage = new Storage<>();56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " + 58 strStorage.isGreaterThan("Apple"));public boolean isGreaterThan(T other)
pass 1 of 250public boolean isGreaterThan(T otherApple) {51 return valueHello != null && value.compareTo(otherApple) > 0;52}intStorage ← ⟨MultipleBounds$1Storage A⟩
56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " + 58 strStorage.isGreaterThan("Apple"));5960Storage<Integer> intStorage→ ⟨MultipleBounds$1Storage A⟩ = new Storage<>();61intStorage.store(42);62System.out.println(" Greater than 30: " +output Greater than 'Apple': truethis.value ← 42
pass 2 of 241public void store(T value42) {42 this.value→ 42 = value42;43 System.out.println(" Stored (serializable): " + value42);44}output Stored (serializable): 42intStorage.store(42);
60Storage<Integer> intStorage = new Storage<>();61intStorage.store(42);62System.out.println(" Greater than 30: " + 63 intStorage.isGreaterThan(30));public boolean isGreaterThan(T other)
pass 2 of 250public boolean isGreaterThan(T other30) {51 return value42 != null && value.compareTo(other30) > 0;52}System.out.println(" Greater than 30: " +
61intStorage.store(42);62System.out.println(" Greater than 30: " + 63 intStorage.isGreaterThan(30));6465System.out.println("\nCustom interfaces:");output Greater than 30: true Custom interfaces:this.id ← 1, this.name ← Alice
92User(long id1, String nameAlice) {93 this.id→ 1 = id1;94 this.name→ Alice = nameAlice;95}this.item ← ⟨MultipleBounds$1User B⟩
78public Entity(T item⟨MultipleBounds$1User B⟩) {79 this.item→ ⟨MultipleBounds$1User B⟩ = item⟨MultipleBounds$1User B⟩;80}userEntity.display();
104Entity<User> userEntity = new Entity<>(new User(1, "Alice"));105userEntity.display();@Override public long getId()
100 @Override101 public long getId() { return id1; }102}@Override public String getName()
97@Override98public String getName() { return nameAlice; }System.out.println(" ID: " + item.getId() +
82 public void display() {83 System.out.println(" ID: " + item.getId() + 84 ", Name: " + item.getName());85 }86}8788class User implements Nameable, Identifiable {89 private long id;90 private String name;91 92 User(long id, String name) {93 this.id = id;94 this.name = name;95 }96 97 @Override98 public String getName() { return name; }99 100 @Override101 public long getId() { return id; }102}103104Entity<User> userEntity = new Entity<>(new User(1, "Alice"));105userEntity.display();106107System.out.println("\nThree bounds:");output ID: 1, Name: Alice Three bounds:this.resource ← ⟨MultipleBounds$1File C⟩
124public Resource(T resource⟨MultipleBounds$1File C⟩) {125 this.resource→ ⟨MultipleBounds$1File C⟩ = resource⟨MultipleBounds$1File C⟩;126}fileResource.process();
153 Resource<File> fileResource = new Resource<>(new File());154 fileResource.process();155}@Override public String read()
139@Override140public String read() { return contentFile content; }data ← File content
128public void process() {129 String data→ File content = resource.read();130 System.out.println(" Read: " + dataFile content);131 resource.write("Processed: " + dataFile content);132 resource.close();output Read: File content@Override public void write(String data)
130 System.out.println(" Read: " + data);131 resource.write("Processed: " + dataFile content);132 resource.close();133 }134}135136class File implements Readable, Writable, Closeable {137 private String content = "File content";138 139 @Override140 public String read() { return content; }141 142 @Override143 public void write(String dataProcessed: File content) { 144 System.out.println(" Writing: " + dataProcessed: File content);145 }output Writing: Processed: File content@Override public void close()
131 resource.write("Processed: " + data);132 resource.close();133 }134}135136class File implements Readable, Writable, Closeable {137 private String content = "File content";138 139 @Override140 public String read() { return content; }141 142 @Override143 public void write(String data) { 144 System.out.println(" Writing: " + data);145 }146 147 @Override148 public void close() { 149 System.out.println(" Closed");150 }output ClosedfileResource.process();
153 Resource<File> fileResource = new Resource<>(new File());154 fileResource.process();155}
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Multiple bounds:\n");20 21 Calculator<Integer> intCalc = new Calculator<>();22 System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23 System.out.println(" Add(5, 10): " + intCalc.add(5, 10));outputMultiple bounds: Multiple bounds:public T max(T a, T b)
pass 1 of 44static class Calculator<T extends Number & Comparable<T>> {5 public T max(T a5, T b10) {6 return a.compareTo(b10) > 0 ? a5 : b;7 }All 4 passes — pass 1 is the card above pass ab1 5 10 2 5 10 3 3.14 2.71 4 3.14 2.71 System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
21Calculator<Integer> intCalc = new Calculator<>();22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));output Max(5, 10): 10System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
21Calculator<Integer> intCalc = new Calculator<>();22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 4;output Max(5, 10): 10public double add(T a, T b)
pass 1 of 29public double add(T a5, T b10) {10 return a.doubleValue() + b.doubleValue();11}System.out.println(" Add(5, 10): " + intCalc.add(5, 10));
22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 4;output Add(5, 10): 15.0public double add(T a, T b)
pass 2 of 29public double add(T a5, T b10) {10 return a.doubleValue() + b.doubleValue();11}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 4;25System.out.println(" InRange(" + rangeValue4 + ", 5, 10): " +26 intCalc.inRange(rangeValue4, 5, 10));output Add(5, 10): 15.0public boolean inRange(T value, T min, T max)
pass 1 of 213public boolean inRange(T value4, T min5, T max10) {14 return value.compareTo(min5) >= 0 && value.compareTo(max10) <= 0;15}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
24int rangeValue = 4;25System.out.println(" InRange(" + rangeValue4 + ", 5, 10): " +26 intCalc.inRange(rangeValue4, 5, 10));output InRange(4, 5, 10): falsepublic boolean inRange(T value, T min, T max)
pass 2 of 213public boolean inRange(T value4, T min5, T max10) {14 return value.compareTo(min5) >= 0 && value.compareTo(max10) <= 0;15}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
24int rangeValue = 4;25System.out.println(" InRange(" + rangeValue4 + ", 5, 10): " +26 intCalc.inRange(rangeValue4, 5, 10));2728Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));output InRange(4, 5, 10): falseSystem.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71))…
28Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));output Max(3.14, 2.71): 3.14System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71))…
28Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));3031// Multiple bounds: <T extends Type1 & Type2 & Type3>32// Class bound must come first (can only have one class)33// Interface bounds follow, separated by &34// T must satisfy ALL bounds3536System.out.println("\nSerializable + Comparable:");3738class Storage<T extends Serializable & Comparable<T>> {39 private T value;40 41 public void store(T value) {42 this.value = value;43 System.out.println(" Stored (serializable): " + value);44 }45 46 public T retrieve() {47 return value;48 }49 50 public boolean isGreaterThan(T other) {51 return value != null && value.compareTo(other) > 0;52 }53}5455Storage<String> strStorage = new Storage<>();56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " +output Max(3.14, 2.71): 3.14 Serializable + Comparable: Serializable + Comparable:this.value ← Hello
pass 1 of 241public void store(T valueHello) {42 this.value→ Hello = valueHello;43 System.out.println(" Stored (serializable): " + valueHello);44}output Stored (serializable): HellostrStorage.store("Hello");
55Storage<String> strStorage = new Storage<>();56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " + 58 strStorage.isGreaterThan("Apple"));public boolean isGreaterThan(T other)
pass 1 of 250public boolean isGreaterThan(T otherApple) {51 return valueHello != null && value.compareTo(otherApple) > 0;52}intStorage ← ⟨MultipleBounds$1Storage A⟩
56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " + 58 strStorage.isGreaterThan("Apple"));5960Storage<Integer> intStorage→ ⟨MultipleBounds$1Storage A⟩ = new Storage<>();61intStorage.store(42);62System.out.println(" Greater than 30: " +output Greater than 'Apple': truethis.value ← 42
pass 2 of 241public void store(T value42) {42 this.value→ 42 = value42;43 System.out.println(" Stored (serializable): " + value42);44}output Stored (serializable): 42intStorage.store(42);
60Storage<Integer> intStorage = new Storage<>();61intStorage.store(42);62System.out.println(" Greater than 30: " + 63 intStorage.isGreaterThan(30));public boolean isGreaterThan(T other)
pass 2 of 250public boolean isGreaterThan(T other30) {51 return value42 != null && value.compareTo(other30) > 0;52}System.out.println(" Greater than 30: " +
61intStorage.store(42);62System.out.println(" Greater than 30: " + 63 intStorage.isGreaterThan(30));6465System.out.println("\nCustom interfaces:");output Greater than 30: true Custom interfaces:this.id ← 1, this.name ← Alice
92User(long id1, String nameAlice) {93 this.id→ 1 = id1;94 this.name→ Alice = nameAlice;95}this.item ← ⟨MultipleBounds$1User B⟩
78public Entity(T item⟨MultipleBounds$1User B⟩) {79 this.item→ ⟨MultipleBounds$1User B⟩ = item⟨MultipleBounds$1User B⟩;80}userEntity.display();
104Entity<User> userEntity = new Entity<>(new User(1, "Alice"));105userEntity.display();@Override public long getId()
100 @Override101 public long getId() { return id1; }102}@Override public String getName()
97@Override98public String getName() { return nameAlice; }System.out.println(" ID: " + item.getId() +
82 public void display() {83 System.out.println(" ID: " + item.getId() + 84 ", Name: " + item.getName());85 }86}8788class User implements Nameable, Identifiable {89 private long id;90 private String name;91 92 User(long id, String name) {93 this.id = id;94 this.name = name;95 }96 97 @Override98 public String getName() { return name; }99 100 @Override101 public long getId() { return id; }102}103104Entity<User> userEntity = new Entity<>(new User(1, "Alice"));105userEntity.display();106107System.out.println("\nThree bounds:");output ID: 1, Name: Alice Three bounds:this.resource ← ⟨MultipleBounds$1File C⟩
124public Resource(T resource⟨MultipleBounds$1File C⟩) {125 this.resource→ ⟨MultipleBounds$1File C⟩ = resource⟨MultipleBounds$1File C⟩;126}fileResource.process();
153 Resource<File> fileResource = new Resource<>(new File());154 fileResource.process();155}@Override public String read()
139@Override140public String read() { return contentFile content; }data ← File content
128public void process() {129 String data→ File content = resource.read();130 System.out.println(" Read: " + dataFile content);131 resource.write("Processed: " + dataFile content);132 resource.close();output Read: File content@Override public void write(String data)
130 System.out.println(" Read: " + data);131 resource.write("Processed: " + dataFile content);132 resource.close();133 }134}135136class File implements Readable, Writable, Closeable {137 private String content = "File content";138 139 @Override140 public String read() { return content; }141 142 @Override143 public void write(String dataProcessed: File content) { 144 System.out.println(" Writing: " + dataProcessed: File content);145 }output Writing: Processed: File content@Override public void close()
131 resource.write("Processed: " + data);132 resource.close();133 }134}135136class File implements Readable, Writable, Closeable {137 private String content = "File content";138 139 @Override140 public String read() { return content; }141 142 @Override143 public void write(String data) { 144 System.out.println(" Writing: " + data);145 }146 147 @Override148 public void close() { 149 System.out.println(" Closed");150 }output ClosedfileResource.process();
153 Resource<File> fileResource = new Resource<>(new File());154 fileResource.process();155}
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Multiple bounds:\n");20 21 Calculator<Integer> intCalc = new Calculator<>();22 System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23 System.out.println(" Add(5, 10): " + intCalc.add(5, 10));outputMultiple bounds: Multiple bounds:public T max(T a, T b)
pass 1 of 44static class Calculator<T extends Number & Comparable<T>> {5 public T max(T a5, T b10) {6 return a.compareTo(b10) > 0 ? a5 : b;7 }All 4 passes — pass 1 is the card above pass ab1 5 10 2 5 10 3 3.14 2.71 4 3.14 2.71 System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
21Calculator<Integer> intCalc = new Calculator<>();22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));output Max(5, 10): 10System.out.println(" Max(5, 10): " + intCalc.max(5, 10));
21Calculator<Integer> intCalc = new Calculator<>();22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 12;output Max(5, 10): 10public double add(T a, T b)
pass 1 of 29public double add(T a5, T b10) {10 return a.doubleValue() + b.doubleValue();11}System.out.println(" Add(5, 10): " + intCalc.add(5, 10));
22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 12;output Add(5, 10): 15.0public double add(T a, T b)
pass 2 of 29public double add(T a5, T b10) {10 return a.doubleValue() + b.doubleValue();11}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
22System.out.println(" Max(5, 10): " + intCalc.max(5, 10));23System.out.println(" Add(5, 10): " + intCalc.add(5, 10));24int rangeValue = 12;25System.out.println(" InRange(" + rangeValue12 + ", 5, 10): " +26 intCalc.inRange(rangeValue12, 5, 10));output Add(5, 10): 15.0public boolean inRange(T value, T min, T max)
pass 1 of 213public boolean inRange(T value12, T min5, T max10) {14 return value.compareTo(min5) >= 0 && value.compareTo(max10) <= 0;15}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
24int rangeValue = 12;25System.out.println(" InRange(" + rangeValue12 + ", 5, 10): " +26 intCalc.inRange(rangeValue12, 5, 10));output InRange(12, 5, 10): falsepublic boolean inRange(T value, T min, T max)
pass 2 of 213public boolean inRange(T value12, T min5, T max10) {14 return value.compareTo(min5) >= 0 && value.compareTo(max10) <= 0;15}System.out.println(" InRange(" + rangeValue + ", 5, 10): " +
24int rangeValue = 12;25System.out.println(" InRange(" + rangeValue12 + ", 5, 10): " +26 intCalc.inRange(rangeValue12, 5, 10));2728Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));output InRange(12, 5, 10): falseSystem.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71))…
28Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));output Max(3.14, 2.71): 3.14System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71))…
28Calculator<Double> doubleCalc = new Calculator<>();29System.out.println(" Max(3.14, 2.71): " + doubleCalc.max(3.14, 2.71));3031// Multiple bounds: <T extends Type1 & Type2 & Type3>32// Class bound must come first (can only have one class)33// Interface bounds follow, separated by &34// T must satisfy ALL bounds3536System.out.println("\nSerializable + Comparable:");3738class Storage<T extends Serializable & Comparable<T>> {39 private T value;40 41 public void store(T value) {42 this.value = value;43 System.out.println(" Stored (serializable): " + value);44 }45 46 public T retrieve() {47 return value;48 }49 50 public boolean isGreaterThan(T other) {51 return value != null && value.compareTo(other) > 0;52 }53}5455Storage<String> strStorage = new Storage<>();56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " +output Max(3.14, 2.71): 3.14 Serializable + Comparable: Serializable + Comparable:this.value ← Hello
pass 1 of 241public void store(T valueHello) {42 this.value→ Hello = valueHello;43 System.out.println(" Stored (serializable): " + valueHello);44}output Stored (serializable): HellostrStorage.store("Hello");
55Storage<String> strStorage = new Storage<>();56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " + 58 strStorage.isGreaterThan("Apple"));public boolean isGreaterThan(T other)
pass 1 of 250public boolean isGreaterThan(T otherApple) {51 return valueHello != null && value.compareTo(otherApple) > 0;52}intStorage ← ⟨MultipleBounds$1Storage A⟩
56strStorage.store("Hello");57System.out.println(" Greater than 'Apple': " + 58 strStorage.isGreaterThan("Apple"));5960Storage<Integer> intStorage→ ⟨MultipleBounds$1Storage A⟩ = new Storage<>();61intStorage.store(42);62System.out.println(" Greater than 30: " +output Greater than 'Apple': truethis.value ← 42
pass 2 of 241public void store(T value42) {42 this.value→ 42 = value42;43 System.out.println(" Stored (serializable): " + value42);44}output Stored (serializable): 42intStorage.store(42);
60Storage<Integer> intStorage = new Storage<>();61intStorage.store(42);62System.out.println(" Greater than 30: " + 63 intStorage.isGreaterThan(30));public boolean isGreaterThan(T other)
pass 2 of 250public boolean isGreaterThan(T other30) {51 return value42 != null && value.compareTo(other30) > 0;52}System.out.println(" Greater than 30: " +
61intStorage.store(42);62System.out.println(" Greater than 30: " + 63 intStorage.isGreaterThan(30));6465System.out.println("\nCustom interfaces:");output Greater than 30: true Custom interfaces:this.id ← 1, this.name ← Alice
92User(long id1, String nameAlice) {93 this.id→ 1 = id1;94 this.name→ Alice = nameAlice;95}this.item ← ⟨MultipleBounds$1User B⟩
78public Entity(T item⟨MultipleBounds$1User B⟩) {79 this.item→ ⟨MultipleBounds$1User B⟩ = item⟨MultipleBounds$1User B⟩;80}userEntity.display();
104Entity<User> userEntity = new Entity<>(new User(1, "Alice"));105userEntity.display();@Override public long getId()
100 @Override101 public long getId() { return id1; }102}@Override public String getName()
97@Override98public String getName() { return nameAlice; }System.out.println(" ID: " + item.getId() +
82 public void display() {83 System.out.println(" ID: " + item.getId() + 84 ", Name: " + item.getName());85 }86}8788class User implements Nameable, Identifiable {89 private long id;90 private String name;91 92 User(long id, String name) {93 this.id = id;94 this.name = name;95 }96 97 @Override98 public String getName() { return name; }99 100 @Override101 public long getId() { return id; }102}103104Entity<User> userEntity = new Entity<>(new User(1, "Alice"));105userEntity.display();106107System.out.println("\nThree bounds:");output ID: 1, Name: Alice Three bounds:this.resource ← ⟨MultipleBounds$1File C⟩
124public Resource(T resource⟨MultipleBounds$1File C⟩) {125 this.resource→ ⟨MultipleBounds$1File C⟩ = resource⟨MultipleBounds$1File C⟩;126}fileResource.process();
153 Resource<File> fileResource = new Resource<>(new File());154 fileResource.process();155}@Override public String read()
139@Override140public String read() { return contentFile content; }data ← File content
128public void process() {129 String data→ File content = resource.read();130 System.out.println(" Read: " + dataFile content);131 resource.write("Processed: " + dataFile content);132 resource.close();output Read: File content@Override public void write(String data)
130 System.out.println(" Read: " + data);131 resource.write("Processed: " + dataFile content);132 resource.close();133 }134}135136class File implements Readable, Writable, Closeable {137 private String content = "File content";138 139 @Override140 public String read() { return content; }141 142 @Override143 public void write(String dataProcessed: File content) { 144 System.out.println(" Writing: " + dataProcessed: File content);145 }output Writing: Processed: File content@Override public void close()
131 resource.write("Processed: " + data);132 resource.close();133 }134}135136class File implements Readable, Writable, Closeable {137 private String content = "File content";138 139 @Override140 public String read() { return content; }141 142 @Override143 public void write(String data) { 144 System.out.println(" Writing: " + data);145 }146 147 @Override148 public void close() { 149 System.out.println(" Closed");150 }output ClosedfileResource.process();
153 Resource<File> fileResource = new Resource<>(new File());154 fileResource.process();155}
<T extends Number & Comparable<T>> - class first, then interfaces with &.
Bounded methods
Apply bounds to method-level type parameters.
import java.util.*;
public class BoundedMethods {
public static <T extends Comparable<T>> T findMax(List<T> list) {
if (list.isEmpty()) {
return null;
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
public static void main(String[] args) {
System.out.println("Bounded methods:\n");
List<Integer> numbers = Arrays.asList(5, 2, 9, 1, 7);
Integer maxNum = findMax(numbers);
System.out.println(" Max number: " + maxNum);
List<String> words = Arrays.asList("apple", "zebra", "banana");
String maxWord = findMax(words);
System.out.println(" Max word: " + maxWord);
// Method can declare its own type parameters with bounds
// <T extends Type> before return type
// Bound applies only to that method
// Enables calling bounded type's methods
System.out.println("\nNumeric operations:");
class MathUtils {
public static <T extends Number> double sum(List<T> numbers) {
double total = 0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
public static <T extends Number> double average(List<T> numbers) {
return sum(numbers) / numbers.size();
}
}
List<Integer> intList = Arrays.asList(10, 20, 30);
System.out.println(" Sum: " + MathUtils.sum(intList));
System.out.println(" Average: " + MathUtils.average(intList));
List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);
System.out.println(" Sum: " + MathUtils.sum(doubleList));
System.out.println("\nCount matching:");
class Counter {
public static <T> int countMatching(List<T> list, T target) {
int count = 0;
for (T item : list) {
if (item.equals(target)) {
count++;
}
}
return count;
}
public static <T extends Comparable<T>> int countGreater(
List<T> list, T threshold) {
int count = 0;
for (T item : list) {
if (item.compareTo(threshold) > 0) {
count++;
}
}
return count;
}
}
List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);
System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
System.out.println("\nCopy method:");
class Copier {
public static <T> void copy(List<T> source, List<T> dest) {
dest.clear();
dest.addAll(source);
}
public static <T extends Comparable<T>> void copyGreater(
List<T> source, List<T> dest, T threshold) {
dest.clear();
for (T item : source) {
if (item.compareTo(threshold) > 0) {
dest.add(item);
}
}
}
}
List<Integer> src = Arrays.asList(1, 5, 3, 8, 2, 9);
List<Integer> dst = new ArrayList<>();
int threshold = 4;
Copier.copyGreater(src, dst, threshold);
System.out.println(" Copied > " + threshold + ": " + dst);
System.out.println("\nMin/Max finder:");
class MinMax {
public static <T extends Comparable<T>> T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
public static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public static <T extends Comparable<T>> T clamp(
T value, T min, T max) {
if (value.compareTo(min) < 0) return min;
if (value.compareTo(max) > 0) return max;
return value;
}
}
System.out.println(" min(5, 10): " + MinMax.min(5, 10));
System.out.println(" max(5, 10): " + MinMax.max(5, 10));
System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));
System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));
}
}
import java.util.*;
public class BoundedMethods {
public static <T extends Comparable<T>> T findMax(List<T> list) {
if (list.isEmpty()) {
return null;
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
public static void main(String[] args) {
System.out.println("Bounded methods:\n");
List<Integer> numbers = Arrays.asList(5, 2, 9, 1, 7);
Integer maxNum = findMax(numbers);
System.out.println(" Max number: " + maxNum);
List<String> words = Arrays.asList("apple", "zebra", "banana");
String maxWord = findMax(words);
System.out.println(" Max word: " + maxWord);
// Method can declare its own type parameters with bounds
// <T extends Type> before return type
// Bound applies only to that method
// Enables calling bounded type's methods
System.out.println("\nNumeric operations:");
class MathUtils {
public static <T extends Number> double sum(List<T> numbers) {
double total = 0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
public static <T extends Number> double average(List<T> numbers) {
return sum(numbers) / numbers.size();
}
}
List<Integer> intList = Arrays.asList(10, 20, 30);
System.out.println(" Sum: " + MathUtils.sum(intList));
System.out.println(" Average: " + MathUtils.average(intList));
List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);
System.out.println(" Sum: " + MathUtils.sum(doubleList));
System.out.println("\nCount matching:");
class Counter {
public static <T> int countMatching(List<T> list, T target) {
int count = 0;
for (T item : list) {
if (item.equals(target)) {
count++;
}
}
return count;
}
public static <T extends Comparable<T>> int countGreater(
List<T> list, T threshold) {
int count = 0;
for (T item : list) {
if (item.compareTo(threshold) > 0) {
count++;
}
}
return count;
}
}
List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);
System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
System.out.println("\nCopy method:");
class Copier {
public static <T> void copy(List<T> source, List<T> dest) {
dest.clear();
dest.addAll(source);
}
public static <T extends Comparable<T>> void copyGreater(
List<T> source, List<T> dest, T threshold) {
dest.clear();
for (T item : source) {
if (item.compareTo(threshold) > 0) {
dest.add(item);
}
}
}
}
List<Integer> src = Arrays.asList(1, 5, 3, 8, 2, 9);
List<Integer> dst = new ArrayList<>();
int threshold = 6;
Copier.copyGreater(src, dst, threshold);
System.out.println(" Copied > " + threshold + ": " + dst);
System.out.println("\nMin/Max finder:");
class MinMax {
public static <T extends Comparable<T>> T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
public static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public static <T extends Comparable<T>> T clamp(
T value, T min, T max) {
if (value.compareTo(min) < 0) return min;
if (value.compareTo(max) > 0) return max;
return value;
}
}
System.out.println(" min(5, 10): " + MinMax.min(5, 10));
System.out.println(" max(5, 10): " + MinMax.max(5, 10));
System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));
System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));
}
}
import java.util.*;
public class BoundedMethods {
public static <T extends Comparable<T>> T findMax(List<T> list) {
if (list.isEmpty()) {
return null;
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
public static void main(String[] args) {
System.out.println("Bounded methods:\n");
List<Integer> numbers = Arrays.asList(5, 2, 9, 1, 7);
Integer maxNum = findMax(numbers);
System.out.println(" Max number: " + maxNum);
List<String> words = Arrays.asList("apple", "zebra", "banana");
String maxWord = findMax(words);
System.out.println(" Max word: " + maxWord);
// Method can declare its own type parameters with bounds
// <T extends Type> before return type
// Bound applies only to that method
// Enables calling bounded type's methods
System.out.println("\nNumeric operations:");
class MathUtils {
public static <T extends Number> double sum(List<T> numbers) {
double total = 0;
for (T num : numbers) {
total += num.doubleValue();
}
return total;
}
public static <T extends Number> double average(List<T> numbers) {
return sum(numbers) / numbers.size();
}
}
List<Integer> intList = Arrays.asList(10, 20, 30);
System.out.println(" Sum: " + MathUtils.sum(intList));
System.out.println(" Average: " + MathUtils.average(intList));
List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);
System.out.println(" Sum: " + MathUtils.sum(doubleList));
System.out.println("\nCount matching:");
class Counter {
public static <T> int countMatching(List<T> list, T target) {
int count = 0;
for (T item : list) {
if (item.equals(target)) {
count++;
}
}
return count;
}
public static <T extends Comparable<T>> int countGreater(
List<T> list, T threshold) {
int count = 0;
for (T item : list) {
if (item.compareTo(threshold) > 0) {
count++;
}
}
return count;
}
}
List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);
System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
System.out.println("\nCopy method:");
class Copier {
public static <T> void copy(List<T> source, List<T> dest) {
dest.clear();
dest.addAll(source);
}
public static <T extends Comparable<T>> void copyGreater(
List<T> source, List<T> dest, T threshold) {
dest.clear();
for (T item : source) {
if (item.compareTo(threshold) > 0) {
dest.add(item);
}
}
}
}
List<Integer> src = Arrays.asList(1, 5, 3, 8, 2, 9);
List<Integer> dst = new ArrayList<>();
int threshold = 8;
Copier.copyGreater(src, dst, threshold);
System.out.println(" Copied > " + threshold + ": " + dst);
System.out.println("\nMin/Max finder:");
class MinMax {
public static <T extends Comparable<T>> T min(T a, T b) {
return a.compareTo(b) < 0 ? a : b;
}
public static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
public static <T extends Comparable<T>> T clamp(
T value, T min, T max) {
if (value.compareTo(min) < 0) return min;
if (value.compareTo(max) > 0) return max;
return value;
}
}
System.out.println(" min(5, 10): " + MinMax.min(5, 10));
System.out.println(" max(5, 10): " + MinMax.max(5, 10));
System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));
System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));
}
}
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Bounded methods:\n");outputBounded methods: Bounded methods:max ← 5
pass 1 of 23public class BoundedMethods {4 public static <T extends Comparable<T>> T findMax(List<T> list[5, 2, 9, 1, 7]) {5 if (list.isEmpty()) {6 return null;7 }8 9 T max→ 5 = list.get(0);10 for (T item : list) {for (T item : list)
pass 1 of 89T max = list.get(0);10for (T item5 : list[5, 2, 9, 1, 7]) {11 if (item.compareTo(max) > 0) {All 8 passes — pass 1 is the card above pass itemlistmax1 5 [5, 2, 9, 1, 7] — 2 2 [5, 2, 9, 1, 7] — 3 9 [5, 2, 9, 1, 7] 5 → 9 4 1 [5, 2, 9, 1, 7] — 5 7 [5, 2, 9, 1, 7] — 6 apple [apple, zebra, banana] — 7 zebra [apple, zebra, banana] apple → zebra 8 banana [apple, zebra, banana] — max ← 9
pass 1 of 210for (T item : list) {11 if (item.compareTo(max5) > 0) {12 max→ 9 = item9;13 }return max;
14 }15 return max9;16}System.out.println(" Max number: " + maxNum);
22Integer maxNum = findMax(numbers);23System.out.println(" Max number: " + maxNum9);output Max number: 9 Max number: 9max ← apple
pass 2 of 23public class BoundedMethods {4 public static <T extends Comparable<T>> T findMax(List<T> list[apple, zebra, banana]) {5 if (list.isEmpty()) {6 return null;7 }8 9 T max→ apple = list.get(0);10 for (T item : list) {max ← zebra
pass 2 of 210for (T item : list) {11 if (item.compareTo(maxapple) > 0) {12 max→ zebra = itemzebra;13 }return max;
14 }15 return maxzebra;16}System.out.println(" Max word: " + maxWord);
26String maxWord = findMax(words);27System.out.println(" Max word: " + maxWordzebra);2829// Method can declare its own type parameters with bounds30// <T extends Type> before return type31// Bound applies only to that method32// Enables calling bounded type's methods3334System.out.println("\nNumeric operations:");3536class MathUtils {37 public static <T extends Number> double sum(List<T> numbers) {38 double total = 0;39 for (T num : numbers) {40 total += num.doubleValue();41 }42 return total;43 }44 45 public static <T extends Number> double average(List<T> numbers) {46 return sum(numbers) / numbers.size();47 }48}4950List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList));output Max word: zebra Max word: zebra Numeric operations: Numeric operations:total ← 0.0
pass 1 of 636class MathUtils {37 public static <T extends Number> double sum(List<T> numbers[10, 20, 30]) {38 double total→ 0.0 = 0;39 for (T num : numbers) {All 6 passes — pass 1 is the card above pass numberstotal1 [10, 20, 30] 0.0 2 [10, 20, 30] 0.0 3 [10, 20, 30] 0.0 4 [10, 20, 30] 0.0 5 [1.5, 2.5, 3.5] 0.0 6 [1.5, 2.5, 3.5] 0.0 total ← 10.0
pass 1 of 1838double total = 0;39for (T num10 : numbers[10, 20, 30]) {40 total→ 10.0 += num.doubleValue();41}18 passes — pass 1 is the card above pass numnumberstotal1 10 [10, 20, 30] 0.0 → 10.0 2 20 [10, 20, 30] 10.0 → 30.0 3 30 [10, 20, 30] 30.0 → 60.0 4 10 [10, 20, 30] 0.0 → 10.0 5 20 [10, 20, 30] 10.0 → 30.0 6 30 [10, 20, 30] 30.0 → 60.0 7 10 [10, 20, 30] 0.0 → 10.0 8 20 [10, 20, 30] 10.0 → 30.0 9 30 [10, 20, 30] 30.0 → 60.0 ⋯ 7 more passes ⋯ 17 2.5 [1.5, 2.5, 3.5] 1.5 → 4.0 18 3.5 [1.5, 2.5, 3.5] 4.0 → 7.5 return total;
41 }42 return total60.0;43}System.out.println(" Sum: " + MathUtils.sum(intList));
50List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList));output Sum: 60.0return total;
41 }42 return total60.0;43}System.out.println(" Sum: " + MathUtils.sum(intList));
50List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));output Sum: 60.0public static <T extends Number> double average(List<T> numbers)
pass 1 of 245public static <T extends Number> double average(List<T> numbers[10, 20, 30]) {46 return sum(numbers[10, 20, 30]) / numbers.size();47}return total;
41 }42 return total60.0;43}System.out.println(" Average: " + MathUtils.average(intList));
51System.out.println(" Sum: " + MathUtils.sum(intList));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));output Average: 20.0public static <T extends Number> double average(List<T> numbers)
pass 2 of 245public static <T extends Number> double average(List<T> numbers[10, 20, 30]) {46 return sum(numbers[10, 20, 30]) / numbers.size();47}return total;
41 }42 return total60.0;43}System.out.println(" Average: " + MathUtils.average(intList));
51System.out.println(" Sum: " + MathUtils.sum(intList));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));5354List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));output Average: 20.0return total;
41 }42 return total7.5;43}System.out.println(" Sum: " + MathUtils.sum(doubleList));
54List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));output Sum: 7.5return total;
41 }42 return total7.5;43}System.out.println(" Sum: " + MathUtils.sum(doubleList));
54List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));5657System.out.println("\nCount matching:");5859class Counter {60 public static <T> int countMatching(List<T> list, T target) {61 int count = 0;62 for (T item : list) {63 if (item.equals(target)) {64 count++;65 }66 }67 return count;68 }69 70 public static <T extends Comparable<T>> int countGreater(71 List<T> list, T threshold) {72 int count = 0;73 for (T item : list) {74 if (item.compareTo(threshold) > 0) {75 count++;76 }77 }78 return count;79 }80}8182List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));output Sum: 7.5 Count matching: Count matching:count ← 0
pass 1 of 259class Counter {60 public static <T> int countMatching(List<T> list[5, 10, 3, 10, 7], T target10) {61 int count→ 0 = 0;62 for (T item : list) {for (T item : list)
pass 1 of 1061int count = 0;62for (T item5 : list[5, 10, 3, 10, 7]) {63 if (item.equals(target)) {All 10 passes — pass 1 is the card above pass item1 5 2 10 3 3 4 10 5 7 6 5 7 10 8 3 9 10 10 7 count ← 1
pass 1 of 462for (T item : list) {63 if (item.equals(target10)) {64 count→ 1++;65 }All 4 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 0 → 1 4 1 → 2 return count;
66 }67 return count2;68}System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
82List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));output Count 10s: 2count ← 0
pass 2 of 259class Counter {60 public static <T> int countMatching(List<T> list[5, 10, 3, 10, 7], T target10) {61 int count→ 0 = 0;62 for (T item : list) {return count;
66 }67 return count2;68}System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
82List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));output Count 10s: 2count ← 0
pass 1 of 270public static <T extends Comparable<T>> int countGreater(71 List<T> list[5, 10, 3, 10, 7], T threshold5) {72 int count→ 0 = 0;73 for (T item : list) {for (T item : list)
pass 1 of 1072int count = 0;73for (T item5 : list[5, 10, 3, 10, 7]) {74 if (item.compareTo(threshold) > 0) {All 10 passes — pass 1 is the card above pass item1 5 2 10 3 3 4 10 5 7 6 5 7 10 8 3 9 10 10 7 count ← 1
pass 1 of 673for (T item : list) {74 if (item.compareTo(threshold5) > 0) {75 count→ 1++;76 }All 6 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 2 → 3 4 0 → 1 5 1 → 2 6 2 → 3 return count;
77 }78 return count3;79}System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
83System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));output Count > 5: 3count ← 0
pass 2 of 270public static <T extends Comparable<T>> int countGreater(71 List<T> list[5, 10, 3, 10, 7], T threshold5) {72 int count→ 0 = 0;73 for (T item : list) {return count;
77 }78 return count3;79}System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
83System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));8586System.out.println("\nCopy method:");output Count > 5: 3 Copy method: Copy method:public static <T extends Comparable<T>> void copyGreater( …
94public static <T extends Comparable<T>> void copyGreater(95 List<T> source[1, 5, 3, 8, 2, 9], List<T> dest[], T threshold4) {96 dest.clear();97 for (T item : source) {for (T item : source)
pass 1 of 696dest.clear();97for (T item1 : source[1, 5, 3, 8, 2, 9]) {98 if (item.compareTo(threshold) > 0) {All 6 passes — pass 1 is the card above pass item1 1 2 5 3 3 4 8 5 2 6 9 if (item.compareTo(threshold) > 0)
pass 1 of 397for (T item : source) {98 if (item.compareTo(threshold4) > 0) {99 dest.add(item5);100 }All 3 passes — pass 1 is the card above pass item1 5 2 8 3 9 System.out.println(" Copied > " + threshold + ": " + dst);
109Copier.copyGreater(src, dst, threshold);110System.out.println(" Copied > " + threshold4 + ": " + dst[5, 8, 9]);111112System.out.println("\nMin/Max finder:");output Copied > 4: [5, 8, 9] Copied > 4: [5, 8, 9] Min/Max finder: Min/Max finder:public static <T extends Comparable<T>> T min(T a, T b)
114class MinMax {115 public static <T extends Comparable<T>> T min(T a5, T b10) {116 return a.compareTo(b10) < 0 ? a5 : b;117 }System.out.println(" max(5, 10): " + MinMax.max(5, 10));
131System.out.println(" min(5, 10): " + MinMax.min(5, 10));132System.out.println(" max(5, 10): " + MinMax.max(5, 10));133System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));public static <T extends Comparable<T>> T max(T a, T b)
119public static <T extends Comparable<T>> T max(T a5, T b10) {120 return a.compareTo(b10) > 0 ? a5 : b;121}System.out.println(" max(5, 10): " + MinMax.max(5, 10));
131System.out.println(" min(5, 10): " + MinMax.min(5, 10));132System.out.println(" max(5, 10): " + MinMax.max(5, 10));133System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));output max(5, 10): 10public static <T extends Comparable<T>> T clamp( T…
pass 1 of 2123public static <T extends Comparable<T>> T clamp(124 T value15, T min0, T max10) {125 if (value.compareTo(min) < 0) return min;if (value.compareTo(max) > 0)
125if (value.compareTo(min) < 0) return min;126if (value.compareTo(max10) > 0) return max;127return value;System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));
132 System.out.println(" max(5, 10): " + MinMax.max(5, 10));133 System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134 System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));135}output clamp(15, 0, 10): 10public static <T extends Comparable<T>> T clamp( T…
pass 2 of 2123public static <T extends Comparable<T>> T clamp(124 T value-5, T min0, T max10) {125 if (value.compareTo(min) < 0) return min;if (value.compareTo(min) < 0)
124 T value, T min, T max) {125if (value.compareTo(min0) < 0) return min;126if (value.compareTo(max) > 0) return max;System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));
133 System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134 System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));135}output clamp(-5, 0, 10): 0
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Bounded methods:\n");outputBounded methods: Bounded methods:max ← 5
pass 1 of 23public class BoundedMethods {4 public static <T extends Comparable<T>> T findMax(List<T> list[5, 2, 9, 1, 7]) {5 if (list.isEmpty()) {6 return null;7 }8 9 T max→ 5 = list.get(0);10 for (T item : list) {for (T item : list)
pass 1 of 89T max = list.get(0);10for (T item5 : list[5, 2, 9, 1, 7]) {11 if (item.compareTo(max) > 0) {All 8 passes — pass 1 is the card above pass itemlistmax1 5 [5, 2, 9, 1, 7] — 2 2 [5, 2, 9, 1, 7] — 3 9 [5, 2, 9, 1, 7] 5 → 9 4 1 [5, 2, 9, 1, 7] — 5 7 [5, 2, 9, 1, 7] — 6 apple [apple, zebra, banana] — 7 zebra [apple, zebra, banana] apple → zebra 8 banana [apple, zebra, banana] — max ← 9
pass 1 of 210for (T item : list) {11 if (item.compareTo(max5) > 0) {12 max→ 9 = item9;13 }return max;
14 }15 return max9;16}System.out.println(" Max number: " + maxNum);
22Integer maxNum = findMax(numbers);23System.out.println(" Max number: " + maxNum9);output Max number: 9 Max number: 9max ← apple
pass 2 of 23public class BoundedMethods {4 public static <T extends Comparable<T>> T findMax(List<T> list[apple, zebra, banana]) {5 if (list.isEmpty()) {6 return null;7 }8 9 T max→ apple = list.get(0);10 for (T item : list) {max ← zebra
pass 2 of 210for (T item : list) {11 if (item.compareTo(maxapple) > 0) {12 max→ zebra = itemzebra;13 }return max;
14 }15 return maxzebra;16}System.out.println(" Max word: " + maxWord);
26String maxWord = findMax(words);27System.out.println(" Max word: " + maxWordzebra);2829// Method can declare its own type parameters with bounds30// <T extends Type> before return type31// Bound applies only to that method32// Enables calling bounded type's methods3334System.out.println("\nNumeric operations:");3536class MathUtils {37 public static <T extends Number> double sum(List<T> numbers) {38 double total = 0;39 for (T num : numbers) {40 total += num.doubleValue();41 }42 return total;43 }44 45 public static <T extends Number> double average(List<T> numbers) {46 return sum(numbers) / numbers.size();47 }48}4950List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList));output Max word: zebra Max word: zebra Numeric operations: Numeric operations:total ← 0.0
pass 1 of 636class MathUtils {37 public static <T extends Number> double sum(List<T> numbers[10, 20, 30]) {38 double total→ 0.0 = 0;39 for (T num : numbers) {All 6 passes — pass 1 is the card above pass numberstotal1 [10, 20, 30] 0.0 2 [10, 20, 30] 0.0 3 [10, 20, 30] 0.0 4 [10, 20, 30] 0.0 5 [1.5, 2.5, 3.5] 0.0 6 [1.5, 2.5, 3.5] 0.0 total ← 10.0
pass 1 of 1838double total = 0;39for (T num10 : numbers[10, 20, 30]) {40 total→ 10.0 += num.doubleValue();41}18 passes — pass 1 is the card above pass numnumberstotal1 10 [10, 20, 30] 0.0 → 10.0 2 20 [10, 20, 30] 10.0 → 30.0 3 30 [10, 20, 30] 30.0 → 60.0 4 10 [10, 20, 30] 0.0 → 10.0 5 20 [10, 20, 30] 10.0 → 30.0 6 30 [10, 20, 30] 30.0 → 60.0 7 10 [10, 20, 30] 0.0 → 10.0 8 20 [10, 20, 30] 10.0 → 30.0 9 30 [10, 20, 30] 30.0 → 60.0 ⋯ 7 more passes ⋯ 17 2.5 [1.5, 2.5, 3.5] 1.5 → 4.0 18 3.5 [1.5, 2.5, 3.5] 4.0 → 7.5 return total;
41 }42 return total60.0;43}System.out.println(" Sum: " + MathUtils.sum(intList));
50List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList));output Sum: 60.0return total;
41 }42 return total60.0;43}System.out.println(" Sum: " + MathUtils.sum(intList));
50List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));output Sum: 60.0public static <T extends Number> double average(List<T> numbers)
pass 1 of 245public static <T extends Number> double average(List<T> numbers[10, 20, 30]) {46 return sum(numbers[10, 20, 30]) / numbers.size();47}return total;
41 }42 return total60.0;43}System.out.println(" Average: " + MathUtils.average(intList));
51System.out.println(" Sum: " + MathUtils.sum(intList));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));output Average: 20.0public static <T extends Number> double average(List<T> numbers)
pass 2 of 245public static <T extends Number> double average(List<T> numbers[10, 20, 30]) {46 return sum(numbers[10, 20, 30]) / numbers.size();47}return total;
41 }42 return total60.0;43}System.out.println(" Average: " + MathUtils.average(intList));
51System.out.println(" Sum: " + MathUtils.sum(intList));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));5354List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));output Average: 20.0return total;
41 }42 return total7.5;43}System.out.println(" Sum: " + MathUtils.sum(doubleList));
54List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));output Sum: 7.5return total;
41 }42 return total7.5;43}System.out.println(" Sum: " + MathUtils.sum(doubleList));
54List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));5657System.out.println("\nCount matching:");5859class Counter {60 public static <T> int countMatching(List<T> list, T target) {61 int count = 0;62 for (T item : list) {63 if (item.equals(target)) {64 count++;65 }66 }67 return count;68 }69 70 public static <T extends Comparable<T>> int countGreater(71 List<T> list, T threshold) {72 int count = 0;73 for (T item : list) {74 if (item.compareTo(threshold) > 0) {75 count++;76 }77 }78 return count;79 }80}8182List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));output Sum: 7.5 Count matching: Count matching:count ← 0
pass 1 of 259class Counter {60 public static <T> int countMatching(List<T> list[5, 10, 3, 10, 7], T target10) {61 int count→ 0 = 0;62 for (T item : list) {for (T item : list)
pass 1 of 1061int count = 0;62for (T item5 : list[5, 10, 3, 10, 7]) {63 if (item.equals(target)) {All 10 passes — pass 1 is the card above pass item1 5 2 10 3 3 4 10 5 7 6 5 7 10 8 3 9 10 10 7 count ← 1
pass 1 of 462for (T item : list) {63 if (item.equals(target10)) {64 count→ 1++;65 }All 4 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 0 → 1 4 1 → 2 return count;
66 }67 return count2;68}System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
82List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));output Count 10s: 2count ← 0
pass 2 of 259class Counter {60 public static <T> int countMatching(List<T> list[5, 10, 3, 10, 7], T target10) {61 int count→ 0 = 0;62 for (T item : list) {return count;
66 }67 return count2;68}System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
82List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));output Count 10s: 2count ← 0
pass 1 of 270public static <T extends Comparable<T>> int countGreater(71 List<T> list[5, 10, 3, 10, 7], T threshold5) {72 int count→ 0 = 0;73 for (T item : list) {for (T item : list)
pass 1 of 1072int count = 0;73for (T item5 : list[5, 10, 3, 10, 7]) {74 if (item.compareTo(threshold) > 0) {All 10 passes — pass 1 is the card above pass item1 5 2 10 3 3 4 10 5 7 6 5 7 10 8 3 9 10 10 7 count ← 1
pass 1 of 673for (T item : list) {74 if (item.compareTo(threshold5) > 0) {75 count→ 1++;76 }All 6 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 2 → 3 4 0 → 1 5 1 → 2 6 2 → 3 return count;
77 }78 return count3;79}System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
83System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));output Count > 5: 3count ← 0
pass 2 of 270public static <T extends Comparable<T>> int countGreater(71 List<T> list[5, 10, 3, 10, 7], T threshold5) {72 int count→ 0 = 0;73 for (T item : list) {return count;
77 }78 return count3;79}System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
83System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));8586System.out.println("\nCopy method:");output Count > 5: 3 Copy method: Copy method:public static <T extends Comparable<T>> void copyGreater( …
94public static <T extends Comparable<T>> void copyGreater(95 List<T> source[1, 5, 3, 8, 2, 9], List<T> dest[], T threshold6) {96 dest.clear();97 for (T item : source) {for (T item : source)
pass 1 of 696dest.clear();97for (T item1 : source[1, 5, 3, 8, 2, 9]) {98 if (item.compareTo(threshold) > 0) {All 6 passes — pass 1 is the card above pass itemthreshold1 1 — 2 5 — 3 3 — 4 8 6 5 2 — 6 9 6 if (item.compareTo(threshold) > 0)
pass 1 of 297for (T item : source) {98 if (item.compareTo(threshold6) > 0) {99 dest.add(item8);100 }if (item.compareTo(threshold) > 0)
pass 2 of 297for (T item : source) {98 if (item.compareTo(threshold6) > 0) {99 dest.add(item9);100 }System.out.println(" Copied > " + threshold + ": " + dst);
109Copier.copyGreater(src, dst, threshold);110System.out.println(" Copied > " + threshold6 + ": " + dst[8, 9]);111112System.out.println("\nMin/Max finder:");output Copied > 6: [8, 9] Copied > 6: [8, 9] Min/Max finder: Min/Max finder:public static <T extends Comparable<T>> T min(T a, T b)
114class MinMax {115 public static <T extends Comparable<T>> T min(T a5, T b10) {116 return a.compareTo(b10) < 0 ? a5 : b;117 }System.out.println(" max(5, 10): " + MinMax.max(5, 10));
131System.out.println(" min(5, 10): " + MinMax.min(5, 10));132System.out.println(" max(5, 10): " + MinMax.max(5, 10));133System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));public static <T extends Comparable<T>> T max(T a, T b)
119public static <T extends Comparable<T>> T max(T a5, T b10) {120 return a.compareTo(b10) > 0 ? a5 : b;121}System.out.println(" max(5, 10): " + MinMax.max(5, 10));
131System.out.println(" min(5, 10): " + MinMax.min(5, 10));132System.out.println(" max(5, 10): " + MinMax.max(5, 10));133System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));output max(5, 10): 10public static <T extends Comparable<T>> T clamp( T…
pass 1 of 2123public static <T extends Comparable<T>> T clamp(124 T value15, T min0, T max10) {125 if (value.compareTo(min) < 0) return min;if (value.compareTo(max) > 0)
125if (value.compareTo(min) < 0) return min;126if (value.compareTo(max10) > 0) return max;127return value;System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));
132 System.out.println(" max(5, 10): " + MinMax.max(5, 10));133 System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134 System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));135}output clamp(15, 0, 10): 10public static <T extends Comparable<T>> T clamp( T…
pass 2 of 2123public static <T extends Comparable<T>> T clamp(124 T value-5, T min0, T max10) {125 if (value.compareTo(min) < 0) return min;if (value.compareTo(min) < 0)
124 T value, T min, T max) {125if (value.compareTo(min0) < 0) return min;126if (value.compareTo(max) > 0) return max;System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));
133 System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134 System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));135}output clamp(-5, 0, 10): 0
public static void main(String[] args)
18public static void main(String[] args) {19 System.out.println("Bounded methods:\n");outputBounded methods: Bounded methods:max ← 5
pass 1 of 23public class BoundedMethods {4 public static <T extends Comparable<T>> T findMax(List<T> list[5, 2, 9, 1, 7]) {5 if (list.isEmpty()) {6 return null;7 }8 9 T max→ 5 = list.get(0);10 for (T item : list) {for (T item : list)
pass 1 of 89T max = list.get(0);10for (T item5 : list[5, 2, 9, 1, 7]) {11 if (item.compareTo(max) > 0) {All 8 passes — pass 1 is the card above pass itemlistmax1 5 [5, 2, 9, 1, 7] — 2 2 [5, 2, 9, 1, 7] — 3 9 [5, 2, 9, 1, 7] 5 → 9 4 1 [5, 2, 9, 1, 7] — 5 7 [5, 2, 9, 1, 7] — 6 apple [apple, zebra, banana] — 7 zebra [apple, zebra, banana] apple → zebra 8 banana [apple, zebra, banana] — max ← 9
pass 1 of 210for (T item : list) {11 if (item.compareTo(max5) > 0) {12 max→ 9 = item9;13 }return max;
14 }15 return max9;16}System.out.println(" Max number: " + maxNum);
22Integer maxNum = findMax(numbers);23System.out.println(" Max number: " + maxNum9);output Max number: 9 Max number: 9max ← apple
pass 2 of 23public class BoundedMethods {4 public static <T extends Comparable<T>> T findMax(List<T> list[apple, zebra, banana]) {5 if (list.isEmpty()) {6 return null;7 }8 9 T max→ apple = list.get(0);10 for (T item : list) {max ← zebra
pass 2 of 210for (T item : list) {11 if (item.compareTo(maxapple) > 0) {12 max→ zebra = itemzebra;13 }return max;
14 }15 return maxzebra;16}System.out.println(" Max word: " + maxWord);
26String maxWord = findMax(words);27System.out.println(" Max word: " + maxWordzebra);2829// Method can declare its own type parameters with bounds30// <T extends Type> before return type31// Bound applies only to that method32// Enables calling bounded type's methods3334System.out.println("\nNumeric operations:");3536class MathUtils {37 public static <T extends Number> double sum(List<T> numbers) {38 double total = 0;39 for (T num : numbers) {40 total += num.doubleValue();41 }42 return total;43 }44 45 public static <T extends Number> double average(List<T> numbers) {46 return sum(numbers) / numbers.size();47 }48}4950List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList));output Max word: zebra Max word: zebra Numeric operations: Numeric operations:total ← 0.0
pass 1 of 636class MathUtils {37 public static <T extends Number> double sum(List<T> numbers[10, 20, 30]) {38 double total→ 0.0 = 0;39 for (T num : numbers) {All 6 passes — pass 1 is the card above pass numberstotal1 [10, 20, 30] 0.0 2 [10, 20, 30] 0.0 3 [10, 20, 30] 0.0 4 [10, 20, 30] 0.0 5 [1.5, 2.5, 3.5] 0.0 6 [1.5, 2.5, 3.5] 0.0 total ← 10.0
pass 1 of 1838double total = 0;39for (T num10 : numbers[10, 20, 30]) {40 total→ 10.0 += num.doubleValue();41}18 passes — pass 1 is the card above pass numnumberstotal1 10 [10, 20, 30] 0.0 → 10.0 2 20 [10, 20, 30] 10.0 → 30.0 3 30 [10, 20, 30] 30.0 → 60.0 4 10 [10, 20, 30] 0.0 → 10.0 5 20 [10, 20, 30] 10.0 → 30.0 6 30 [10, 20, 30] 30.0 → 60.0 7 10 [10, 20, 30] 0.0 → 10.0 8 20 [10, 20, 30] 10.0 → 30.0 9 30 [10, 20, 30] 30.0 → 60.0 ⋯ 7 more passes ⋯ 17 2.5 [1.5, 2.5, 3.5] 1.5 → 4.0 18 3.5 [1.5, 2.5, 3.5] 4.0 → 7.5 return total;
41 }42 return total60.0;43}System.out.println(" Sum: " + MathUtils.sum(intList));
50List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList));output Sum: 60.0return total;
41 }42 return total60.0;43}System.out.println(" Sum: " + MathUtils.sum(intList));
50List<Integer> intList = Arrays.asList(10, 20, 30);51System.out.println(" Sum: " + MathUtils.sum(intList[10, 20, 30]));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));output Sum: 60.0public static <T extends Number> double average(List<T> numbers)
pass 1 of 245public static <T extends Number> double average(List<T> numbers[10, 20, 30]) {46 return sum(numbers[10, 20, 30]) / numbers.size();47}return total;
41 }42 return total60.0;43}System.out.println(" Average: " + MathUtils.average(intList));
51System.out.println(" Sum: " + MathUtils.sum(intList));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));output Average: 20.0public static <T extends Number> double average(List<T> numbers)
pass 2 of 245public static <T extends Number> double average(List<T> numbers[10, 20, 30]) {46 return sum(numbers[10, 20, 30]) / numbers.size();47}return total;
41 }42 return total60.0;43}System.out.println(" Average: " + MathUtils.average(intList));
51System.out.println(" Sum: " + MathUtils.sum(intList));52System.out.println(" Average: " + MathUtils.average(intList[10, 20, 30]));5354List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));output Average: 20.0return total;
41 }42 return total7.5;43}System.out.println(" Sum: " + MathUtils.sum(doubleList));
54List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));output Sum: 7.5return total;
41 }42 return total7.5;43}System.out.println(" Sum: " + MathUtils.sum(doubleList));
54List<Double> doubleList = Arrays.asList(1.5, 2.5, 3.5);55System.out.println(" Sum: " + MathUtils.sum(doubleList[1.5, 2.5, 3.5]));5657System.out.println("\nCount matching:");5859class Counter {60 public static <T> int countMatching(List<T> list, T target) {61 int count = 0;62 for (T item : list) {63 if (item.equals(target)) {64 count++;65 }66 }67 return count;68 }69 70 public static <T extends Comparable<T>> int countGreater(71 List<T> list, T threshold) {72 int count = 0;73 for (T item : list) {74 if (item.compareTo(threshold) > 0) {75 count++;76 }77 }78 return count;79 }80}8182List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));output Sum: 7.5 Count matching: Count matching:count ← 0
pass 1 of 259class Counter {60 public static <T> int countMatching(List<T> list[5, 10, 3, 10, 7], T target10) {61 int count→ 0 = 0;62 for (T item : list) {for (T item : list)
pass 1 of 1061int count = 0;62for (T item5 : list[5, 10, 3, 10, 7]) {63 if (item.equals(target)) {All 10 passes — pass 1 is the card above pass item1 5 2 10 3 3 4 10 5 7 6 5 7 10 8 3 9 10 10 7 count ← 1
pass 1 of 462for (T item : list) {63 if (item.equals(target10)) {64 count→ 1++;65 }All 4 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 0 → 1 4 1 → 2 return count;
66 }67 return count2;68}System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
82List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));output Count 10s: 2count ← 0
pass 2 of 259class Counter {60 public static <T> int countMatching(List<T> list[5, 10, 3, 10, 7], T target10) {61 int count→ 0 = 0;62 for (T item : list) {return count;
66 }67 return count2;68}System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));
82List<Integer> nums = Arrays.asList(5, 10, 3, 10, 7);83System.out.println(" Count 10s: " + Counter.countMatching(nums[5, 10, 3, 10, 7], 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));output Count 10s: 2count ← 0
pass 1 of 270public static <T extends Comparable<T>> int countGreater(71 List<T> list[5, 10, 3, 10, 7], T threshold5) {72 int count→ 0 = 0;73 for (T item : list) {for (T item : list)
pass 1 of 1072int count = 0;73for (T item5 : list[5, 10, 3, 10, 7]) {74 if (item.compareTo(threshold) > 0) {All 10 passes — pass 1 is the card above pass item1 5 2 10 3 3 4 10 5 7 6 5 7 10 8 3 9 10 10 7 count ← 1
pass 1 of 673for (T item : list) {74 if (item.compareTo(threshold5) > 0) {75 count→ 1++;76 }All 6 passes — pass 1 is the card above pass count1 0 → 1 2 1 → 2 3 2 → 3 4 0 → 1 5 1 → 2 6 2 → 3 return count;
77 }78 return count3;79}System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
83System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));output Count > 5: 3count ← 0
pass 2 of 270public static <T extends Comparable<T>> int countGreater(71 List<T> list[5, 10, 3, 10, 7], T threshold5) {72 int count→ 0 = 0;73 for (T item : list) {return count;
77 }78 return count3;79}System.out.println(" Count > 5: " + Counter.countGreater(nums, 5));
83System.out.println(" Count 10s: " + Counter.countMatching(nums, 10));84System.out.println(" Count > 5: " + Counter.countGreater(nums[5, 10, 3, 10, 7], 5));8586System.out.println("\nCopy method:");output Count > 5: 3 Copy method: Copy method:public static <T extends Comparable<T>> void copyGreater( …
94public static <T extends Comparable<T>> void copyGreater(95 List<T> source[1, 5, 3, 8, 2, 9], List<T> dest[], T threshold8) {96 dest.clear();97 for (T item : source) {for (T item : source)
pass 1 of 696dest.clear();97for (T item1 : source[1, 5, 3, 8, 2, 9]) {98 if (item.compareTo(threshold) > 0) {All 6 passes — pass 1 is the card above pass itemthreshold1 1 — 2 5 — 3 3 — 4 8 — 5 2 — 6 9 8 if (item.compareTo(threshold) > 0)
97for (T item : source) {98 if (item.compareTo(threshold8) > 0) {99 dest.add(item9);100 }System.out.println(" Copied > " + threshold + ": " + dst);
109Copier.copyGreater(src, dst, threshold);110System.out.println(" Copied > " + threshold8 + ": " + dst[9]);111112System.out.println("\nMin/Max finder:");output Copied > 8: [9] Copied > 8: [9] Min/Max finder: Min/Max finder:public static <T extends Comparable<T>> T min(T a, T b)
114class MinMax {115 public static <T extends Comparable<T>> T min(T a5, T b10) {116 return a.compareTo(b10) < 0 ? a5 : b;117 }System.out.println(" max(5, 10): " + MinMax.max(5, 10));
131System.out.println(" min(5, 10): " + MinMax.min(5, 10));132System.out.println(" max(5, 10): " + MinMax.max(5, 10));133System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));public static <T extends Comparable<T>> T max(T a, T b)
119public static <T extends Comparable<T>> T max(T a5, T b10) {120 return a.compareTo(b10) > 0 ? a5 : b;121}System.out.println(" max(5, 10): " + MinMax.max(5, 10));
131System.out.println(" min(5, 10): " + MinMax.min(5, 10));132System.out.println(" max(5, 10): " + MinMax.max(5, 10));133System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));output max(5, 10): 10public static <T extends Comparable<T>> T clamp( T…
pass 1 of 2123public static <T extends Comparable<T>> T clamp(124 T value15, T min0, T max10) {125 if (value.compareTo(min) < 0) return min;if (value.compareTo(max) > 0)
125if (value.compareTo(min) < 0) return min;126if (value.compareTo(max10) > 0) return max;127return value;System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));
132 System.out.println(" max(5, 10): " + MinMax.max(5, 10));133 System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134 System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));135}output clamp(15, 0, 10): 10public static <T extends Comparable<T>> T clamp( T…
pass 2 of 2123public static <T extends Comparable<T>> T clamp(124 T value-5, T min0, T max10) {125 if (value.compareTo(min) < 0) return min;if (value.compareTo(min) < 0)
124 T value, T min, T max) {125if (value.compareTo(min0) < 0) return min;126if (value.compareTo(max) > 0) return max;System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));
133 System.out.println(" clamp(15, 0, 10): " + MinMax.clamp(15, 0, 10));134 System.out.println(" clamp(-5, 0, 10): " + MinMax.clamp(-5, 0, 10));135}output clamp(-5, 0, 10): 0
<T extends Comparable<T>> T max(T a, T b) - can compare a and b.
Recursive bounds
Type parameter references itself in bound.
import java.util.*;
public class RecursiveBounds {
static class SortedList<T extends Comparable<T>> {
private List<T> items = new ArrayList<>();
public void add(T item) {
items.add(item);
Collections.sort(items);
System.out.println(" Added and sorted: " + item);
}
public T getMin() {
return items.isEmpty() ? null : items.get(0);
}
public T getMax() {
return items.isEmpty() ? null : items.get(items.size() - 1);
}
public List<T> getAll() {
return new ArrayList<>(items);
}
}
public static void main(String[] args) {
System.out.println("Recursive type bounds:\n");
SortedList<Integer> numbers = new SortedList<>();
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
System.out.println(" Min: " + numbers.getMin());
System.out.println(" Max: " + numbers.getMax());
System.out.println(" All: " + numbers.getAll());
// <T extends Comparable<T>> is a recursive bound
// T must be comparable to itself
// Common pattern for sortable types
// Ensures type-safe comparison
System.out.println("\nWith enums:");
enum Priority implements Comparable<Priority> {
LOW, MEDIUM, HIGH
}
SortedList<Priority> priorities = new SortedList<>();
priorities.add(Priority.HIGH);
priorities.add(Priority.LOW);
priorities.add(Priority.MEDIUM);
System.out.println(" Sorted: " + priorities.getAll());
System.out.println("\nCustom comparable:");
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 + ")";
}
}
SortedList<Person> people = new SortedList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
System.out.println(" By age: " + people.getAll());
System.out.println("\nMax finder:");
class MaxFinder {
public static <T extends Comparable<T>> T max(T a, T b, T c) {
T temp = a.compareTo(b) > 0 ? a : b;
return temp.compareTo(c) > 0 ? temp : c;
}
public static <T extends Comparable<T>> T maxOf(List<T> items) {
if (items.isEmpty()) {
return null;
}
T max = items.get(0);
for (T item : items) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
}
Integer maxNum = MaxFinder.max(5, 10, 3);
System.out.println(" Max(5, 10, 3): " + maxNum);
String maxStr = MaxFinder.max("apple", "zebra", "banana");
System.out.println(" Max strings: " + maxStr);
List<Double> doubles = Arrays.asList(3.14, 2.71, 1.41, 1.73);
Double maxDouble = MaxFinder.maxOf(doubles);
System.out.println(" Max double: " + maxDouble);
System.out.println("\nBST node:");
class TreeNode<T extends Comparable<T>> {
T value;
TreeNode<T> left;
TreeNode<T> right;
TreeNode(T value) {
this.value = value;
}
public void insert(T newValue) {
if (newValue.compareTo(value) < 0) {
if (left == null) {
left = new TreeNode<>(newValue);
System.out.println(" Inserted left: " + newValue);
} else {
left.insert(newValue);
}
} else {
if (right == null) {
right = new TreeNode<>(newValue);
System.out.println(" Inserted right: " + newValue);
} else {
right.insert(newValue);
}
}
}
public boolean contains(T target) {
if (value.equals(target)) {
return true;
} else if (target.compareTo(value) < 0) {
return left != null && left.contains(target);
} else {
return right != null && right.contains(target);
}
}
}
TreeNode<Integer> root = new TreeNode<>(50);
root.insert(30);
root.insert(70);
root.insert(20);
root.insert(40);
int searchTarget = 40;
System.out.println(" Contains " + searchTarget + ": " +
root.contains(searchTarget));
System.out.println(" Contains 60: " + root.contains(60));
}
}
import java.util.*;
public class RecursiveBounds {
static class SortedList<T extends Comparable<T>> {
private List<T> items = new ArrayList<>();
public void add(T item) {
items.add(item);
Collections.sort(items);
System.out.println(" Added and sorted: " + item);
}
public T getMin() {
return items.isEmpty() ? null : items.get(0);
}
public T getMax() {
return items.isEmpty() ? null : items.get(items.size() - 1);
}
public List<T> getAll() {
return new ArrayList<>(items);
}
}
public static void main(String[] args) {
System.out.println("Recursive type bounds:\n");
SortedList<Integer> numbers = new SortedList<>();
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
System.out.println(" Min: " + numbers.getMin());
System.out.println(" Max: " + numbers.getMax());
System.out.println(" All: " + numbers.getAll());
// <T extends Comparable<T>> is a recursive bound
// T must be comparable to itself
// Common pattern for sortable types
// Ensures type-safe comparison
System.out.println("\nWith enums:");
enum Priority implements Comparable<Priority> {
LOW, MEDIUM, HIGH
}
SortedList<Priority> priorities = new SortedList<>();
priorities.add(Priority.HIGH);
priorities.add(Priority.LOW);
priorities.add(Priority.MEDIUM);
System.out.println(" Sorted: " + priorities.getAll());
System.out.println("\nCustom comparable:");
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 + ")";
}
}
SortedList<Person> people = new SortedList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
System.out.println(" By age: " + people.getAll());
System.out.println("\nMax finder:");
class MaxFinder {
public static <T extends Comparable<T>> T max(T a, T b, T c) {
T temp = a.compareTo(b) > 0 ? a : b;
return temp.compareTo(c) > 0 ? temp : c;
}
public static <T extends Comparable<T>> T maxOf(List<T> items) {
if (items.isEmpty()) {
return null;
}
T max = items.get(0);
for (T item : items) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
}
Integer maxNum = MaxFinder.max(5, 10, 3);
System.out.println(" Max(5, 10, 3): " + maxNum);
String maxStr = MaxFinder.max("apple", "zebra", "banana");
System.out.println(" Max strings: " + maxStr);
List<Double> doubles = Arrays.asList(3.14, 2.71, 1.41, 1.73);
Double maxDouble = MaxFinder.maxOf(doubles);
System.out.println(" Max double: " + maxDouble);
System.out.println("\nBST node:");
class TreeNode<T extends Comparable<T>> {
T value;
TreeNode<T> left;
TreeNode<T> right;
TreeNode(T value) {
this.value = value;
}
public void insert(T newValue) {
if (newValue.compareTo(value) < 0) {
if (left == null) {
left = new TreeNode<>(newValue);
System.out.println(" Inserted left: " + newValue);
} else {
left.insert(newValue);
}
} else {
if (right == null) {
right = new TreeNode<>(newValue);
System.out.println(" Inserted right: " + newValue);
} else {
right.insert(newValue);
}
}
}
public boolean contains(T target) {
if (value.equals(target)) {
return true;
} else if (target.compareTo(value) < 0) {
return left != null && left.contains(target);
} else {
return right != null && right.contains(target);
}
}
}
TreeNode<Integer> root = new TreeNode<>(50);
root.insert(30);
root.insert(70);
root.insert(20);
root.insert(40);
int searchTarget = 20;
System.out.println(" Contains " + searchTarget + ": " +
root.contains(searchTarget));
System.out.println(" Contains 60: " + root.contains(60));
}
}
import java.util.*;
public class RecursiveBounds {
static class SortedList<T extends Comparable<T>> {
private List<T> items = new ArrayList<>();
public void add(T item) {
items.add(item);
Collections.sort(items);
System.out.println(" Added and sorted: " + item);
}
public T getMin() {
return items.isEmpty() ? null : items.get(0);
}
public T getMax() {
return items.isEmpty() ? null : items.get(items.size() - 1);
}
public List<T> getAll() {
return new ArrayList<>(items);
}
}
public static void main(String[] args) {
System.out.println("Recursive type bounds:\n");
SortedList<Integer> numbers = new SortedList<>();
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
System.out.println(" Min: " + numbers.getMin());
System.out.println(" Max: " + numbers.getMax());
System.out.println(" All: " + numbers.getAll());
// <T extends Comparable<T>> is a recursive bound
// T must be comparable to itself
// Common pattern for sortable types
// Ensures type-safe comparison
System.out.println("\nWith enums:");
enum Priority implements Comparable<Priority> {
LOW, MEDIUM, HIGH
}
SortedList<Priority> priorities = new SortedList<>();
priorities.add(Priority.HIGH);
priorities.add(Priority.LOW);
priorities.add(Priority.MEDIUM);
System.out.println(" Sorted: " + priorities.getAll());
System.out.println("\nCustom comparable:");
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 + ")";
}
}
SortedList<Person> people = new SortedList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
System.out.println(" By age: " + people.getAll());
System.out.println("\nMax finder:");
class MaxFinder {
public static <T extends Comparable<T>> T max(T a, T b, T c) {
T temp = a.compareTo(b) > 0 ? a : b;
return temp.compareTo(c) > 0 ? temp : c;
}
public static <T extends Comparable<T>> T maxOf(List<T> items) {
if (items.isEmpty()) {
return null;
}
T max = items.get(0);
for (T item : items) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
}
Integer maxNum = MaxFinder.max(5, 10, 3);
System.out.println(" Max(5, 10, 3): " + maxNum);
String maxStr = MaxFinder.max("apple", "zebra", "banana");
System.out.println(" Max strings: " + maxStr);
List<Double> doubles = Arrays.asList(3.14, 2.71, 1.41, 1.73);
Double maxDouble = MaxFinder.maxOf(doubles);
System.out.println(" Max double: " + maxDouble);
System.out.println("\nBST node:");
class TreeNode<T extends Comparable<T>> {
T value;
TreeNode<T> left;
TreeNode<T> right;
TreeNode(T value) {
this.value = value;
}
public void insert(T newValue) {
if (newValue.compareTo(value) < 0) {
if (left == null) {
left = new TreeNode<>(newValue);
System.out.println(" Inserted left: " + newValue);
} else {
left.insert(newValue);
}
} else {
if (right == null) {
right = new TreeNode<>(newValue);
System.out.println(" Inserted right: " + newValue);
} else {
right.insert(newValue);
}
}
}
public boolean contains(T target) {
if (value.equals(target)) {
return true;
} else if (target.compareTo(value) < 0) {
return left != null && left.contains(target);
} else {
return right != null && right.contains(target);
}
}
}
TreeNode<Integer> root = new TreeNode<>(50);
root.insert(30);
root.insert(70);
root.insert(20);
root.insert(40);
int searchTarget = 60;
System.out.println(" Contains " + searchTarget + ": " +
root.contains(searchTarget));
System.out.println(" Contains 60: " + root.contains(60));
}
}
public static void main(String[] args)
26public static void main(String[] args) {27 System.out.println("Recursive type bounds:\n");outputRecursive type bounds: Recursive type bounds:public void add(T item)
pass 1 of 107public void add(T item5) {8 items.add(item5);9 Collections.sort(items[5]);10 System.out.println(" Added and sorted: " + item5);11}output Added and sorted: 5All 10 passes — pass 1 is the card above pass itemitems1 5 [5] 2 2 [5, 2] → [2, 5] 3 8 [2, 5, 8] 4 1 [2, 5, 8, 1] → [1, 2, 5, 8] 5 HIGH [HIGH] 6 LOW [HIGH, LOW] → [LOW, HIGH] 7 MEDIUM [LOW, HIGH, MEDIUM] → [LOW, MEDIUM, HIGH] 8 Alice(30) [Alice(30)] 9 Bob(25) [Alice(30), Bob(25)] 10 Charlie(35) [Bob(25), Alice(30), Charlie(35)] System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());output Min: 1System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Min: 1System.out.println(" Max: " + numbers.getMax());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Max: 8System.out.println(" Max: " + numbers.getMax());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Max: 8System.out.println(" All: " + numbers.getAll());
36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output All: [1, 2, 5, 8]System.out.println(" All: " + numbers.getAll());
36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());3839// <T extends Comparable<T>> is a recursive bound40// T must be comparable to itself41// Common pattern for sortable types42// Ensures type-safe comparison4344System.out.println("\nWith enums:");output All: [1, 2, 5, 8] With enums: With enums:System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());output Sorted: [LOW, MEDIUM, HIGH]System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());5657System.out.println("\nCustom comparable:");output Sorted: [LOW, MEDIUM, HIGH] Custom comparable: Custom comparable:this.name ← Alice, this.age ← 30
pass 1 of 363Person(String nameAlice, int age30) {64 this.name→ Alice = nameAlice;65 this.age→ 30 = age30;66}All 3 passes — pass 1 is the card above pass nameagethis.namethis.age1 Alice 30 Alice 30 2 Bob 25 Bob 25 3 Charlie 35 Charlie 35 @Override public int compareTo(Person other)
pass 1 of 368@Override69public int compareTo(Person otherAlice(30)) {70 return Integer.compare(this.age25, other.age30);71}All 3 passes — pass 1 is the card above pass otherthis.ageother.age1 Alice(30) 25 30 2 Bob(25) 30 25 3 Alice(30) 35 30 items ← [Bob(25), Alice(30)]
8 items.add(item);9 Collections.sort(items→ [Bob(25), Alice(30)]);10 System.out.println(" Added and sorted: " + itemBob(25));11}output Added and sorted: Bob(25)Collections.sort(items);
8 items.add(item);9 Collections.sort(items[Bob(25), Alice(30), Charlie(35)]);10 System.out.println(" Added and sorted: " + itemCharlie(35));11 }12 13 public T getMin() {14 return items.isEmpty() ? null : items.get(0);15 }16 17 public T getMax() {18 return items.isEmpty() ? null : items.get(items.size() - 1);19 }20 21 public List<T> getAll() {22 return new ArrayList<>(items);23 }24}2526public static void main(String[] args) {27 System.out.println("Recursive type bounds:\n");28 29 SortedList<Integer> numbers = new SortedList<>();30 numbers.add(5);31 numbers.add(2);32 numbers.add(8);33 numbers.add(1);34 35 System.out.println(" Min: " + numbers.getMin());36 System.out.println(" Max: " + numbers.getMax());37 System.out.println(" All: " + numbers.getAll());38 39 // <T extends Comparable<T>> is a recursive bound40 // T must be comparable to itself41 // Common pattern for sortable types42 // Ensures type-safe comparison43 44 System.out.println("\nWith enums:");45 46 enum Priority implements Comparable<Priority> {47 LOW, MEDIUM, HIGH48 }49 50 SortedList<Priority> priorities = new SortedList<>();51 priorities.add(Priority.HIGH);52 priorities.add(Priority.LOW);53 priorities.add(Priority.MEDIUM);54 55 System.out.println(" Sorted: " + priorities.getAll());56 57 System.out.println("\nCustom comparable:");58 59 class Person implements Comparable<Person> {60 String name;61 int age;62 63 Person(String name, int age) {64 this.name = name;65 this.age = age;66 }67 68 @Override69 public int compareTo(Person other) {70 return Integer.compare(this.age, other.age);71 }72 73 @Override74 public String toString() {75 return name + "(" + age + ")";76 }77 }78 79 SortedList<Person> people = new SortedList<>();80 people.add(new Person("Alice", 30));81 people.add(new Person("Bob", 25));82 people.add(new Person("Charlie", 35));83 84 System.out.println(" By age: " + people.getAll());output Added and sorted: Charlie(35)System.out.println(" By age: " + people.getAll());
84System.out.println(" By age: " + people.getAll());output By age: [Bob(25), Alice(30), Charlie(35)]System.out.println(" By age: " + people.getAll());
84System.out.println(" By age: " + people.getAll());8586System.out.println("\nMax finder:");output By age: [Bob(25), Alice(30), Charlie(35)] Max finder: Max finder:temp ← 10
pass 1 of 288class MaxFinder {89 public static <T extends Comparable<T>> T max(T a5, T b10, T c3) {90 T temp→ 10 = a.compareTo(b10) > 0 ? a5 : b;91 return temp.compareTo(c3) > 0 ? temp10 : c;92 }System.out.println(" Max(5, 10, 3): " + maxNum);
108Integer maxNum = MaxFinder.max(5, 10, 3);109System.out.println(" Max(5, 10, 3): " + maxNum10);output Max(5, 10, 3): 10 Max(5, 10, 3): 10temp ← zebra
pass 2 of 288class MaxFinder {89 public static <T extends Comparable<T>> T max(T aapple, T bzebra, T cbanana) {90 T temp→ zebra = a.compareTo(bzebra) > 0 ? aapple : b;91 return temp.compareTo(cbanana) > 0 ? tempzebra : c;92 }System.out.println(" Max strings: " + maxStr);
111String maxStr = MaxFinder.max("apple", "zebra", "banana");112System.out.println(" Max strings: " + maxStrzebra);output Max strings: zebra Max strings: zebramax ← 3.14
94public static <T extends Comparable<T>> T maxOf(List<T> items[3.14, 2.71, 1.41, 1.73]) {95 if (items.isEmpty()) {96 return null;97 }98 T max→ 3.14 = items.get(0);99 for (T item : items) {for (T item : items)
pass 1 of 498T max = items.get(0);99for (T item3.14 : items[3.14, 2.71, 1.41, 1.73]) {100 if (item.compareTo(max) > 0) {All 4 passes — pass 1 is the card above pass item1 3.14 2 2.71 3 1.41 4 1.73 return max;
103 }104 return max3.14;105}System.out.println(" Max double: " + maxDouble);
115Double maxDouble = MaxFinder.maxOf(doubles);116System.out.println(" Max double: " + maxDouble3.14);117118System.out.println("\nBST node:");output Max double: 3.14 Max double: 3.14 BST node: BST node:this.value ← 50
pass 1 of 5125TreeNode(T value50) {126 this.value→ 50 = value50;127}All 5 passes — pass 1 is the card above pass valuethis.value1 50 50 2 30 30 3 70 70 4 20 20 5 40 40 root.insert(30);
158TreeNode<Integer> root = new TreeNode<>(50);159root.insert(30);160root.insert(70);public void insert(T newValue)
pass 1 of 6129public void insert(T newValue30) {130 if (newValue.compareTo(value) < 0) {All 6 passes — pass 1 is the card above pass newValueleftright1 30 null — 2 70 — null 3 20 — — 4 20 null — 5 40 — — 6 40 — null if (newValue.compareTo(value) < 0)
pass 1 of 4129public void insert(T newValue) {130 if (newValue.compareTo(value50) < 0) {131 if (left == null) {All 4 passes — pass 1 is the card above pass valueleftnewValueright1 50 null — — 2 50 — 20 — 3 30 null — — 4 50 — 40 null if (left == null)
pass 1 of 2130if (newValue.compareTo(value) < 0) {131 if (leftnull == null) {132 left = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue);left ← ⟨RecursiveBounds$1TreeNode A⟩
131if (left == null) {132 left→ ⟨RecursiveBounds$1TreeNode A⟩ = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue30);134} else {output Inserted left: 30root.insert(30);
158TreeNode<Integer> root = new TreeNode<>(50);159root.insert(30);160root.insert(70);161root.insert(20);if (right == null)
pass 1 of 2137} else {138 if (rightnull == null) {139 right = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue);right ← ⟨RecursiveBounds$1TreeNode B⟩
138if (right == null) {139 right→ ⟨RecursiveBounds$1TreeNode B⟩ = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue70);141} else {output Inserted right: 70root.insert(70);
159root.insert(30);160root.insert(70);161root.insert(20);162root.insert(40);else
pass 1 of 2133 System.out.println(" Inserted left: " + newValue);134} else {135 left.insert(newValue20);136}if (left == null)
pass 2 of 2130if (newValue.compareTo(value) < 0) {131 if (leftnull == null) {132 left = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue);left ← ⟨RecursiveBounds$1TreeNode C⟩
131if (left == null) {132 left→ ⟨RecursiveBounds$1TreeNode C⟩ = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue20);134} else {output Inserted left: 20left.insert(newValue);
134} else {135 left.insert(newValue20);136}root.insert(20);
160root.insert(70);161root.insert(20);162root.insert(40);else
pass 2 of 2133 System.out.println(" Inserted left: " + newValue);134} else {135 left.insert(newValue40);136}if (right == null)
pass 2 of 2137} else {138 if (rightnull == null) {139 right = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue);right ← ⟨RecursiveBounds$1TreeNode D⟩
134 } else {135 left.insert(newValue40);136 }137} else {138 if (right == null) {139 right→ ⟨RecursiveBounds$1TreeNode D⟩ = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue40);141 } else {output Inserted right: 40searchTarget ← 40
161root.insert(20);162root.insert(40);163164int searchTarget→ 40 = 40; //@searchTarget=40, 20, 60165System.out.println(" Contains " + searchTarget40 + ": " +166 root.contains(searchTarget40));167System.out.println(" Contains 60: " + root.contains(60));public boolean contains(T target)
pass 1 of 5147public boolean contains(T target40) {148 if (value.equals(target)) {All 5 passes — pass 1 is the card above pass targetvalueleftright1 40 50 ⟨RecursiveBounds$1TreeNode A⟩ — 2 40 — — ⟨RecursiveBounds$1TreeNode D⟩ 3 40 — — — 4 60 — — ⟨RecursiveBounds$1TreeNode B⟩ 5 60 70 null — if (target.compareTo(value) < 0)
pass 1 of 2149 return true;150} else if (target.compareTo(value50) < 0) {151 return left⟨RecursiveBounds$1TreeNode A⟩ != null && left.contains(target40);152} else {else
pass 1 of 2151 return left != null && left.contains(target);152} else {153 return right⟨RecursiveBounds$1TreeNode D⟩ != null && right.contains(target40);154}if (value.equals(target))
147public boolean contains(T target) {148 if (value.equals(target40)) {149 return true;150 } else if (target.compareTo(value) < 0) {System.out.println(" Contains " + searchTarget + ": " +
164 int searchTarget = 40; //@searchTarget=40, 20, 60165 System.out.println(" Contains " + searchTarget40 + ": " +166 root.contains(searchTarget40));167 System.out.println(" Contains 60: " + root.contains(60));168}output Contains 40: trueelse
pass 2 of 2151 return left != null && left.contains(target);152} else {153 return right⟨RecursiveBounds$1TreeNode B⟩ != null && right.contains(target60);154}if (target.compareTo(value) < 0)
pass 2 of 2149 return true;150} else if (target.compareTo(value70) < 0) {151 return leftnull != null && left.contains(target60);152} else {System.out.println(" Contains 60: " + root.contains(60));
166 root.contains(searchTarget));167 System.out.println(" Contains 60: " + root.contains(60));168}output Contains 60: false
public static void main(String[] args)
26public static void main(String[] args) {27 System.out.println("Recursive type bounds:\n");outputRecursive type bounds: Recursive type bounds:public void add(T item)
pass 1 of 107public void add(T item5) {8 items.add(item5);9 Collections.sort(items[5]);10 System.out.println(" Added and sorted: " + item5);11}output Added and sorted: 5All 10 passes — pass 1 is the card above pass itemitems1 5 [5] 2 2 [5, 2] → [2, 5] 3 8 [2, 5, 8] 4 1 [2, 5, 8, 1] → [1, 2, 5, 8] 5 HIGH [HIGH] 6 LOW [HIGH, LOW] → [LOW, HIGH] 7 MEDIUM [LOW, HIGH, MEDIUM] → [LOW, MEDIUM, HIGH] 8 Alice(30) [Alice(30)] 9 Bob(25) [Alice(30), Bob(25)] 10 Charlie(35) [Bob(25), Alice(30), Charlie(35)] System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());output Min: 1System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Min: 1System.out.println(" Max: " + numbers.getMax());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Max: 8System.out.println(" Max: " + numbers.getMax());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Max: 8System.out.println(" All: " + numbers.getAll());
36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output All: [1, 2, 5, 8]System.out.println(" All: " + numbers.getAll());
36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());3839// <T extends Comparable<T>> is a recursive bound40// T must be comparable to itself41// Common pattern for sortable types42// Ensures type-safe comparison4344System.out.println("\nWith enums:");output All: [1, 2, 5, 8] With enums: With enums:System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());output Sorted: [LOW, MEDIUM, HIGH]System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());5657System.out.println("\nCustom comparable:");output Sorted: [LOW, MEDIUM, HIGH] Custom comparable: Custom comparable:this.name ← Alice, this.age ← 30
pass 1 of 363Person(String nameAlice, int age30) {64 this.name→ Alice = nameAlice;65 this.age→ 30 = age30;66}All 3 passes — pass 1 is the card above pass nameagethis.namethis.age1 Alice 30 Alice 30 2 Bob 25 Bob 25 3 Charlie 35 Charlie 35 @Override public int compareTo(Person other)
pass 1 of 368@Override69public int compareTo(Person otherAlice(30)) {70 return Integer.compare(this.age25, other.age30);71}All 3 passes — pass 1 is the card above pass otherthis.ageother.age1 Alice(30) 25 30 2 Bob(25) 30 25 3 Alice(30) 35 30 items ← [Bob(25), Alice(30)]
8 items.add(item);9 Collections.sort(items→ [Bob(25), Alice(30)]);10 System.out.println(" Added and sorted: " + itemBob(25));11}output Added and sorted: Bob(25)Collections.sort(items);
8 items.add(item);9 Collections.sort(items[Bob(25), Alice(30), Charlie(35)]);10 System.out.println(" Added and sorted: " + itemCharlie(35));11 }12 13 public T getMin() {14 return items.isEmpty() ? null : items.get(0);15 }16 17 public T getMax() {18 return items.isEmpty() ? null : items.get(items.size() - 1);19 }20 21 public List<T> getAll() {22 return new ArrayList<>(items);23 }24}2526public static void main(String[] args) {27 System.out.println("Recursive type bounds:\n");28 29 SortedList<Integer> numbers = new SortedList<>();30 numbers.add(5);31 numbers.add(2);32 numbers.add(8);33 numbers.add(1);34 35 System.out.println(" Min: " + numbers.getMin());36 System.out.println(" Max: " + numbers.getMax());37 System.out.println(" All: " + numbers.getAll());38 39 // <T extends Comparable<T>> is a recursive bound40 // T must be comparable to itself41 // Common pattern for sortable types42 // Ensures type-safe comparison43 44 System.out.println("\nWith enums:");45 46 enum Priority implements Comparable<Priority> {47 LOW, MEDIUM, HIGH48 }49 50 SortedList<Priority> priorities = new SortedList<>();51 priorities.add(Priority.HIGH);52 priorities.add(Priority.LOW);53 priorities.add(Priority.MEDIUM);54 55 System.out.println(" Sorted: " + priorities.getAll());56 57 System.out.println("\nCustom comparable:");58 59 class Person implements Comparable<Person> {60 String name;61 int age;62 63 Person(String name, int age) {64 this.name = name;65 this.age = age;66 }67 68 @Override69 public int compareTo(Person other) {70 return Integer.compare(this.age, other.age);71 }72 73 @Override74 public String toString() {75 return name + "(" + age + ")";76 }77 }78 79 SortedList<Person> people = new SortedList<>();80 people.add(new Person("Alice", 30));81 people.add(new Person("Bob", 25));82 people.add(new Person("Charlie", 35));83 84 System.out.println(" By age: " + people.getAll());output Added and sorted: Charlie(35)System.out.println(" By age: " + people.getAll());
84System.out.println(" By age: " + people.getAll());output By age: [Bob(25), Alice(30), Charlie(35)]System.out.println(" By age: " + people.getAll());
84System.out.println(" By age: " + people.getAll());8586System.out.println("\nMax finder:");output By age: [Bob(25), Alice(30), Charlie(35)] Max finder: Max finder:temp ← 10
pass 1 of 288class MaxFinder {89 public static <T extends Comparable<T>> T max(T a5, T b10, T c3) {90 T temp→ 10 = a.compareTo(b10) > 0 ? a5 : b;91 return temp.compareTo(c3) > 0 ? temp10 : c;92 }System.out.println(" Max(5, 10, 3): " + maxNum);
108Integer maxNum = MaxFinder.max(5, 10, 3);109System.out.println(" Max(5, 10, 3): " + maxNum10);output Max(5, 10, 3): 10 Max(5, 10, 3): 10temp ← zebra
pass 2 of 288class MaxFinder {89 public static <T extends Comparable<T>> T max(T aapple, T bzebra, T cbanana) {90 T temp→ zebra = a.compareTo(bzebra) > 0 ? aapple : b;91 return temp.compareTo(cbanana) > 0 ? tempzebra : c;92 }System.out.println(" Max strings: " + maxStr);
111String maxStr = MaxFinder.max("apple", "zebra", "banana");112System.out.println(" Max strings: " + maxStrzebra);output Max strings: zebra Max strings: zebramax ← 3.14
94public static <T extends Comparable<T>> T maxOf(List<T> items[3.14, 2.71, 1.41, 1.73]) {95 if (items.isEmpty()) {96 return null;97 }98 T max→ 3.14 = items.get(0);99 for (T item : items) {for (T item : items)
pass 1 of 498T max = items.get(0);99for (T item3.14 : items[3.14, 2.71, 1.41, 1.73]) {100 if (item.compareTo(max) > 0) {All 4 passes — pass 1 is the card above pass item1 3.14 2 2.71 3 1.41 4 1.73 return max;
103 }104 return max3.14;105}System.out.println(" Max double: " + maxDouble);
115Double maxDouble = MaxFinder.maxOf(doubles);116System.out.println(" Max double: " + maxDouble3.14);117118System.out.println("\nBST node:");output Max double: 3.14 Max double: 3.14 BST node: BST node:this.value ← 50
pass 1 of 5125TreeNode(T value50) {126 this.value→ 50 = value50;127}All 5 passes — pass 1 is the card above pass valuethis.value1 50 50 2 30 30 3 70 70 4 20 20 5 40 40 root.insert(30);
158TreeNode<Integer> root = new TreeNode<>(50);159root.insert(30);160root.insert(70);public void insert(T newValue)
pass 1 of 6129public void insert(T newValue30) {130 if (newValue.compareTo(value) < 0) {All 6 passes — pass 1 is the card above pass newValueleftright1 30 null — 2 70 — null 3 20 — — 4 20 null — 5 40 — — 6 40 — null if (newValue.compareTo(value) < 0)
pass 1 of 4129public void insert(T newValue) {130 if (newValue.compareTo(value50) < 0) {131 if (left == null) {All 4 passes — pass 1 is the card above pass valueleftnewValueright1 50 null — — 2 50 — 20 — 3 30 null — — 4 50 — 40 null if (left == null)
pass 1 of 2130if (newValue.compareTo(value) < 0) {131 if (leftnull == null) {132 left = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue);left ← ⟨RecursiveBounds$1TreeNode A⟩
131if (left == null) {132 left→ ⟨RecursiveBounds$1TreeNode A⟩ = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue30);134} else {output Inserted left: 30root.insert(30);
158TreeNode<Integer> root = new TreeNode<>(50);159root.insert(30);160root.insert(70);161root.insert(20);if (right == null)
pass 1 of 2137} else {138 if (rightnull == null) {139 right = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue);right ← ⟨RecursiveBounds$1TreeNode B⟩
138if (right == null) {139 right→ ⟨RecursiveBounds$1TreeNode B⟩ = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue70);141} else {output Inserted right: 70root.insert(70);
159root.insert(30);160root.insert(70);161root.insert(20);162root.insert(40);else
pass 1 of 2133 System.out.println(" Inserted left: " + newValue);134} else {135 left.insert(newValue20);136}if (left == null)
pass 2 of 2130if (newValue.compareTo(value) < 0) {131 if (leftnull == null) {132 left = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue);left ← ⟨RecursiveBounds$1TreeNode C⟩
131if (left == null) {132 left→ ⟨RecursiveBounds$1TreeNode C⟩ = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue20);134} else {output Inserted left: 20left.insert(newValue);
134} else {135 left.insert(newValue20);136}root.insert(20);
160root.insert(70);161root.insert(20);162root.insert(40);else
pass 2 of 2133 System.out.println(" Inserted left: " + newValue);134} else {135 left.insert(newValue40);136}if (right == null)
pass 2 of 2137} else {138 if (rightnull == null) {139 right = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue);right ← ⟨RecursiveBounds$1TreeNode D⟩
134 } else {135 left.insert(newValue40);136 }137} else {138 if (right == null) {139 right→ ⟨RecursiveBounds$1TreeNode D⟩ = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue40);141 } else {output Inserted right: 40searchTarget ← 20
161root.insert(20);162root.insert(40);163164int searchTarget→ 20 = 20;165System.out.println(" Contains " + searchTarget20 + ": " +166 root.contains(searchTarget20));167System.out.println(" Contains 60: " + root.contains(60));public boolean contains(T target)
pass 1 of 5147public boolean contains(T target20) {148 if (value.equals(target)) {All 5 passes — pass 1 is the card above pass targetright1 20 — 2 20 — 3 20 — 4 60 ⟨RecursiveBounds$1TreeNode B⟩ 5 60 — if (target.compareTo(value) < 0)
pass 1 of 3149 return true;150} else if (target.compareTo(value50) < 0) {151 return left⟨RecursiveBounds$1TreeNode A⟩ != null && left.contains(target20);152} else {All 3 passes — pass 1 is the card above pass valuelefttarget1 50 ⟨RecursiveBounds$1TreeNode A⟩ 20 2 30 ⟨RecursiveBounds$1TreeNode C⟩ 20 3 70 null 60 if (value.equals(target))
147public boolean contains(T target) {148 if (value.equals(target20)) {149 return true;150 } else if (target.compareTo(value) < 0) {System.out.println(" Contains " + searchTarget + ": " +
164 int searchTarget = 20;165 System.out.println(" Contains " + searchTarget20 + ": " +166 root.contains(searchTarget20));167 System.out.println(" Contains 60: " + root.contains(60));168}output Contains 20: trueelse
151 return left != null && left.contains(target);152} else {153 return right⟨RecursiveBounds$1TreeNode B⟩ != null && right.contains(target60);154}System.out.println(" Contains 60: " + root.contains(60));
166 root.contains(searchTarget));167 System.out.println(" Contains 60: " + root.contains(60));168}output Contains 60: false
public static void main(String[] args)
26public static void main(String[] args) {27 System.out.println("Recursive type bounds:\n");outputRecursive type bounds: Recursive type bounds:public void add(T item)
pass 1 of 107public void add(T item5) {8 items.add(item5);9 Collections.sort(items[5]);10 System.out.println(" Added and sorted: " + item5);11}output Added and sorted: 5All 10 passes — pass 1 is the card above pass itemitems1 5 [5] 2 2 [5, 2] → [2, 5] 3 8 [2, 5, 8] 4 1 [2, 5, 8, 1] → [1, 2, 5, 8] 5 HIGH [HIGH] 6 LOW [HIGH, LOW] → [LOW, HIGH] 7 MEDIUM [LOW, HIGH, MEDIUM] → [LOW, MEDIUM, HIGH] 8 Alice(30) [Alice(30)] 9 Bob(25) [Alice(30), Bob(25)] 10 Charlie(35) [Bob(25), Alice(30), Charlie(35)] System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());output Min: 1System.out.println(" Min: " + numbers.getMin());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Min: 1System.out.println(" Max: " + numbers.getMax());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Max: 8System.out.println(" Max: " + numbers.getMax());
35System.out.println(" Min: " + numbers.getMin());36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output Max: 8System.out.println(" All: " + numbers.getAll());
36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());output All: [1, 2, 5, 8]System.out.println(" All: " + numbers.getAll());
36System.out.println(" Max: " + numbers.getMax());37System.out.println(" All: " + numbers.getAll());3839// <T extends Comparable<T>> is a recursive bound40// T must be comparable to itself41// Common pattern for sortable types42// Ensures type-safe comparison4344System.out.println("\nWith enums:");output All: [1, 2, 5, 8] With enums: With enums:System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());output Sorted: [LOW, MEDIUM, HIGH]System.out.println(" Sorted: " + priorities.getAll());
55System.out.println(" Sorted: " + priorities.getAll());5657System.out.println("\nCustom comparable:");output Sorted: [LOW, MEDIUM, HIGH] Custom comparable: Custom comparable:this.name ← Alice, this.age ← 30
pass 1 of 363Person(String nameAlice, int age30) {64 this.name→ Alice = nameAlice;65 this.age→ 30 = age30;66}All 3 passes — pass 1 is the card above pass nameagethis.namethis.age1 Alice 30 Alice 30 2 Bob 25 Bob 25 3 Charlie 35 Charlie 35 @Override public int compareTo(Person other)
pass 1 of 368@Override69public int compareTo(Person otherAlice(30)) {70 return Integer.compare(this.age25, other.age30);71}All 3 passes — pass 1 is the card above pass otherthis.ageother.age1 Alice(30) 25 30 2 Bob(25) 30 25 3 Alice(30) 35 30 items ← [Bob(25), Alice(30)]
8 items.add(item);9 Collections.sort(items→ [Bob(25), Alice(30)]);10 System.out.println(" Added and sorted: " + itemBob(25));11}output Added and sorted: Bob(25)Collections.sort(items);
8 items.add(item);9 Collections.sort(items[Bob(25), Alice(30), Charlie(35)]);10 System.out.println(" Added and sorted: " + itemCharlie(35));11 }12 13 public T getMin() {14 return items.isEmpty() ? null : items.get(0);15 }16 17 public T getMax() {18 return items.isEmpty() ? null : items.get(items.size() - 1);19 }20 21 public List<T> getAll() {22 return new ArrayList<>(items);23 }24}2526public static void main(String[] args) {27 System.out.println("Recursive type bounds:\n");28 29 SortedList<Integer> numbers = new SortedList<>();30 numbers.add(5);31 numbers.add(2);32 numbers.add(8);33 numbers.add(1);34 35 System.out.println(" Min: " + numbers.getMin());36 System.out.println(" Max: " + numbers.getMax());37 System.out.println(" All: " + numbers.getAll());38 39 // <T extends Comparable<T>> is a recursive bound40 // T must be comparable to itself41 // Common pattern for sortable types42 // Ensures type-safe comparison43 44 System.out.println("\nWith enums:");45 46 enum Priority implements Comparable<Priority> {47 LOW, MEDIUM, HIGH48 }49 50 SortedList<Priority> priorities = new SortedList<>();51 priorities.add(Priority.HIGH);52 priorities.add(Priority.LOW);53 priorities.add(Priority.MEDIUM);54 55 System.out.println(" Sorted: " + priorities.getAll());56 57 System.out.println("\nCustom comparable:");58 59 class Person implements Comparable<Person> {60 String name;61 int age;62 63 Person(String name, int age) {64 this.name = name;65 this.age = age;66 }67 68 @Override69 public int compareTo(Person other) {70 return Integer.compare(this.age, other.age);71 }72 73 @Override74 public String toString() {75 return name + "(" + age + ")";76 }77 }78 79 SortedList<Person> people = new SortedList<>();80 people.add(new Person("Alice", 30));81 people.add(new Person("Bob", 25));82 people.add(new Person("Charlie", 35));83 84 System.out.println(" By age: " + people.getAll());output Added and sorted: Charlie(35)System.out.println(" By age: " + people.getAll());
84System.out.println(" By age: " + people.getAll());output By age: [Bob(25), Alice(30), Charlie(35)]System.out.println(" By age: " + people.getAll());
84System.out.println(" By age: " + people.getAll());8586System.out.println("\nMax finder:");output By age: [Bob(25), Alice(30), Charlie(35)] Max finder: Max finder:temp ← 10
pass 1 of 288class MaxFinder {89 public static <T extends Comparable<T>> T max(T a5, T b10, T c3) {90 T temp→ 10 = a.compareTo(b10) > 0 ? a5 : b;91 return temp.compareTo(c3) > 0 ? temp10 : c;92 }System.out.println(" Max(5, 10, 3): " + maxNum);
108Integer maxNum = MaxFinder.max(5, 10, 3);109System.out.println(" Max(5, 10, 3): " + maxNum10);output Max(5, 10, 3): 10 Max(5, 10, 3): 10temp ← zebra
pass 2 of 288class MaxFinder {89 public static <T extends Comparable<T>> T max(T aapple, T bzebra, T cbanana) {90 T temp→ zebra = a.compareTo(bzebra) > 0 ? aapple : b;91 return temp.compareTo(cbanana) > 0 ? tempzebra : c;92 }System.out.println(" Max strings: " + maxStr);
111String maxStr = MaxFinder.max("apple", "zebra", "banana");112System.out.println(" Max strings: " + maxStrzebra);output Max strings: zebra Max strings: zebramax ← 3.14
94public static <T extends Comparable<T>> T maxOf(List<T> items[3.14, 2.71, 1.41, 1.73]) {95 if (items.isEmpty()) {96 return null;97 }98 T max→ 3.14 = items.get(0);99 for (T item : items) {for (T item : items)
pass 1 of 498T max = items.get(0);99for (T item3.14 : items[3.14, 2.71, 1.41, 1.73]) {100 if (item.compareTo(max) > 0) {All 4 passes — pass 1 is the card above pass item1 3.14 2 2.71 3 1.41 4 1.73 return max;
103 }104 return max3.14;105}System.out.println(" Max double: " + maxDouble);
115Double maxDouble = MaxFinder.maxOf(doubles);116System.out.println(" Max double: " + maxDouble3.14);117118System.out.println("\nBST node:");output Max double: 3.14 Max double: 3.14 BST node: BST node:this.value ← 50
pass 1 of 5125TreeNode(T value50) {126 this.value→ 50 = value50;127}All 5 passes — pass 1 is the card above pass valuethis.value1 50 50 2 30 30 3 70 70 4 20 20 5 40 40 root.insert(30);
158TreeNode<Integer> root = new TreeNode<>(50);159root.insert(30);160root.insert(70);public void insert(T newValue)
pass 1 of 6129public void insert(T newValue30) {130 if (newValue.compareTo(value) < 0) {All 6 passes — pass 1 is the card above pass newValueleftright1 30 null — 2 70 — null 3 20 — — 4 20 null — 5 40 — — 6 40 — null if (newValue.compareTo(value) < 0)
pass 1 of 4129public void insert(T newValue) {130 if (newValue.compareTo(value50) < 0) {131 if (left == null) {All 4 passes — pass 1 is the card above pass valueleftnewValueright1 50 null — — 2 50 — 20 — 3 30 null — — 4 50 — 40 null if (left == null)
pass 1 of 2130if (newValue.compareTo(value) < 0) {131 if (leftnull == null) {132 left = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue);left ← ⟨RecursiveBounds$1TreeNode A⟩
131if (left == null) {132 left→ ⟨RecursiveBounds$1TreeNode A⟩ = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue30);134} else {output Inserted left: 30root.insert(30);
158TreeNode<Integer> root = new TreeNode<>(50);159root.insert(30);160root.insert(70);161root.insert(20);if (right == null)
pass 1 of 2137} else {138 if (rightnull == null) {139 right = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue);right ← ⟨RecursiveBounds$1TreeNode B⟩
138if (right == null) {139 right→ ⟨RecursiveBounds$1TreeNode B⟩ = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue70);141} else {output Inserted right: 70root.insert(70);
159root.insert(30);160root.insert(70);161root.insert(20);162root.insert(40);else
pass 1 of 2133 System.out.println(" Inserted left: " + newValue);134} else {135 left.insert(newValue20);136}if (left == null)
pass 2 of 2130if (newValue.compareTo(value) < 0) {131 if (leftnull == null) {132 left = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue);left ← ⟨RecursiveBounds$1TreeNode C⟩
131if (left == null) {132 left→ ⟨RecursiveBounds$1TreeNode C⟩ = new TreeNode<>(newValue);133 System.out.println(" Inserted left: " + newValue20);134} else {output Inserted left: 20left.insert(newValue);
134} else {135 left.insert(newValue20);136}root.insert(20);
160root.insert(70);161root.insert(20);162root.insert(40);else
pass 2 of 2133 System.out.println(" Inserted left: " + newValue);134} else {135 left.insert(newValue40);136}if (right == null)
pass 2 of 2137} else {138 if (rightnull == null) {139 right = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue);right ← ⟨RecursiveBounds$1TreeNode D⟩
134 } else {135 left.insert(newValue40);136 }137} else {138 if (right == null) {139 right→ ⟨RecursiveBounds$1TreeNode D⟩ = new TreeNode<>(newValue);140 System.out.println(" Inserted right: " + newValue40);141 } else {output Inserted right: 40searchTarget ← 60
161root.insert(20);162root.insert(40);163164int searchTarget→ 60 = 60;165System.out.println(" Contains " + searchTarget60 + ": " +166 root.contains(searchTarget60));167System.out.println(" Contains 60: " + root.contains(60));public boolean contains(T target)
pass 1 of 4147public boolean contains(T target60) {148 if (value.equals(target)) {All 4 passes — pass 1 is the card above pass rightvalueleft1 ⟨RecursiveBounds$1TreeNode B⟩ — — 2 — 70 null 3 ⟨RecursiveBounds$1TreeNode B⟩ — — 4 — 70 null else
pass 1 of 2151 return left != null && left.contains(target);152} else {153 return right⟨RecursiveBounds$1TreeNode B⟩ != null && right.contains(target60);154}if (target.compareTo(value) < 0)
pass 1 of 2149 return true;150} else if (target.compareTo(value70) < 0) {151 return leftnull != null && left.contains(target60);152} else {System.out.println(" Contains " + searchTarget + ": " +
164 int searchTarget = 60;165 System.out.println(" Contains " + searchTarget60 + ": " +166 root.contains(searchTarget60));167 System.out.println(" Contains 60: " + root.contains(60));168}output Contains 60: falseelse
pass 2 of 2151 return left != null && left.contains(target);152} else {153 return right⟨RecursiveBounds$1TreeNode B⟩ != null && right.contains(target60);154}if (target.compareTo(value) < 0)
pass 2 of 2149 return true;150} else if (target.compareTo(value70) < 0) {151 return leftnull != null && left.contains(target60);152} else {System.out.println(" Contains 60: " + root.contains(60));
166 root.contains(searchTarget));167 System.out.println(" Contains 60: " + root.contains(60));168}output Contains 60: false
<T extends Comparable<T>> - T comparable to itself. Common for sorting.
Bounds and inheritance
How bounded generics interact with class hierarchies.
import java.util.*;
public class BoundsInheritance {
static abstract class Entity {
private Long id;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
}
static class Repository<T extends Entity> {
private Map<Long, T> store = new LinkedHashMap<>();
private Long nextId = 1L;
public void save(T entity) {
if (entity.getId() == null) {
entity.setId(nextId++);
}
store.put(entity.getId(), entity);
System.out.println(" Saved: " + entity.getClass().getSimpleName() +
" id=" + entity.getId());
}
public T findById(Long id) {
return store.get(id);
}
public List<T> findAll() {
return new ArrayList<>(store.values());
}
public int count() {
return store.size();
}
}
public static void main(String[] args) {
System.out.println("Bounds with inheritance:\n");
class User extends Entity {
String name;
User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User(" + getId() + ", " + name + ")";
}
}
Repository<User> userRepo = new Repository<>();
User user1 = new User("Alice");
User user2 = new User("Bob");
userRepo.save(user1);
userRepo.save(user2);
System.out.println(" All users: " + userRepo.findAll());
System.out.println(" Count: " + userRepo.count());
// Bounded type allows accessing members of bound class
// All entities have getId/setId methods
// Type parameter must extend (or implement) the bound
// Enables polymorphic behavior with type safety
System.out.println("\nMultiple entity types:");
class Product extends Entity {
String name;
double price;
Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Product(" + getId() + ", " + name + ", $" + price + ")";
}
}
Repository<Product> productRepo = new Repository<>();
productRepo.save(new Product("Laptop", 999.99));
productRepo.save(new Product("Mouse", 29.99));
System.out.println(" All products: " + productRepo.findAll());
System.out.println("\nService layer:");
class Service<T extends Entity> {
private Repository<T> repository;
public Service(Repository<T> repository) {
this.repository = repository;
}
public T create(T entity) {
repository.save(entity);
System.out.println(" Created: " + entity);
return entity;
}
public T update(T entity) {
if (entity.getId() == null) {
throw new IllegalArgumentException("Cannot update without ID");
}
repository.save(entity);
System.out.println(" Updated: " + entity);
return entity;
}
public T getById(Long id) {
T entity = repository.findById(id);
if (entity == null) {
System.out.println(" Not found: " + id);
}
return entity;
}
}
Service<User> userService = new Service<>(userRepo);
User newUser = userService.create(new User("Charlie"));
User found = userService.getById(newUser.getId());
System.out.println(" Retrieved: " + found);
System.out.println("\nAuditable entities:");
abstract class Auditable extends Entity {
private long createdAt = 1000L;
public long getCreatedAt() { return createdAt; }
}
class AuditableRepository<T extends Auditable> extends Repository<T> {
@Override
public void save(T entity) {
super.save(entity);
System.out.println(" Created at: " + entity.getCreatedAt());
}
}
class Order extends Auditable {
String product;
int quantity;
Order(String product, int quantity) {
this.product = product;
this.quantity = quantity;
}
@Override
public String toString() {
return "Order(" + getId() + ", " + product + " x" + quantity + ")";
}
}
AuditableRepository<Order> orderRepo = new AuditableRepository<>();
orderRepo.save(new Order("Laptop", 1));
orderRepo.save(new Order("Mouse", 2));
System.out.println("\nType hierarchy:");
abstract class Animal {
abstract String speak();
}
class Dog extends Animal {
@Override
String speak() { return "Woof"; }
}
class Cat extends Animal {
@Override
String speak() { return "Meow"; }
}
class AnimalShelter<T extends Animal> {
private List<T> animals = new ArrayList<>();
public void add(T animal) {
animals.add(animal);
System.out.println(" Added: " + animal.speak());
}
public void makeAllSpeak() {
for (T animal : animals) {
System.out.println(" " + animal.speak());
}
}
}
AnimalShelter<Dog> dogShelter = new AnimalShelter<>();
dogShelter.add(new Dog());
dogShelter.add(new Dog());
dogShelter.makeAllSpeak();
}
}
public static void main(String[] args)
37public static void main(String[] args) {38 System.out.println("Bounds with inheritance:\n");outputBounds with inheritance: Bounds with inheritance:this.name ← Alice
pass 1 of 343User(String nameAlice) {44 this.name→ Alice = nameAlice;45}All 3 passes — pass 1 is the card above pass nameentitythis.name1 Alice — Alice 2 Bob — Bob 3 Charlie User(null, Charlie) Charlie public Long getId()
pass 1 of 1117public Long getId() { return idnull; }8public void setId(Long id) { this.id = id; }111 passes — pass 1 is the card above pass identity1 null — 2 null — 3 null — 4 1 — 5 1 — 6 1 — 7 1 — 8 1 — 9 1 — ⋯ 100 more passes ⋯ 110 2 — 111 2 — public void save(T entity)
pass 1 of 715public void save(T entityUser(null, Alice)) {16 if (entity.getId() == null) {All 7 passes — pass 1 is the card above pass entity1 User(null, Alice) 2 User(null, Bob) 3 Product(null, Laptop, $999.99) 4 Product(null, Mouse, $29.99) 5 User(null, Charlie) 6 Order(null, Laptop x1) 7 Order(null, Mouse x2) if (entity.getId() == null)
pass 1 of 715public void save(T entity) {16 if (entity.getId() == null) {17 entity.setId(nextId1++);18 }All 7 passes — pass 1 is the card above pass nextId1 1 2 2 3 1 4 2 5 3 6 1 7 2 this.id ← 1
pass 1 of 77 public Long getId() { return id; }8 public void setId(Long id1) { this.id→ 1 = id; }9}All 7 passes — pass 1 is the card above pass idthis.id1 1 1 2 2 2 3 1 1 4 2 2 5 3 3 6 1 1 7 2 2 nextId ← 2
16if (entity.getId() == null) {17 entity.setId(nextId→ 2++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityUser(1, Alice));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityUser(1, Alice));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: User id=1nextId ← 3
16if (entity.getId() == null) {17 entity.setId(nextId→ 3++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityUser(2, Bob));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityUser(2, Bob));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: User id=2System.out.println(" All users: " + userRepo.findAll());
61System.out.println(" All users: " + userRepo.findAll());62System.out.println(" Count: " + userRepo.count());System.out.println(" All users: " + userRepo.findAll());
61System.out.println(" All users: " + userRepo.findAll());62System.out.println(" Count: " + userRepo.count());output All users: [User(1, Alice), User(2, Bob)]System.out.println(" All users: " + userRepo.findAll());
61System.out.println(" All users: " + userRepo.findAll());62System.out.println(" Count: " + userRepo.count());output All users: [User(1, Alice), User(2, Bob)]System.out.println(" Count: " + userRepo.count());
61System.out.println(" All users: " + userRepo.findAll());62System.out.println(" Count: " + userRepo.count());output Count: 2System.out.println(" Count: " + userRepo.count());
61System.out.println(" All users: " + userRepo.findAll());62System.out.println(" Count: " + userRepo.count());6364// Bounded type allows accessing members of bound class65// All entities have getId/setId methods66// Type parameter must extend (or implement) the bound67// Enables polymorphic behavior with type safety6869System.out.println("\nMultiple entity types:");output Count: 2 Multiple entity types: Multiple entity types:this.name ← Laptop, this.price ← 999.99
pass 1 of 275Product(String nameLaptop, double price999.99) {76 this.name→ Laptop = nameLaptop;77 this.price→ 999.99 = price999.99;78}nextId ← 2
16if (entity.getId() == null) {17 entity.setId(nextId→ 2++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityProduct(1, Laptop, $999.99));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityProduct(1, Laptop, $999.99));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: Product id=1this.name ← Mouse, this.price ← 29.99
pass 2 of 275Product(String nameMouse, double price29.99) {76 this.name→ Mouse = nameMouse;77 this.price→ 29.99 = price29.99;78}nextId ← 3
16if (entity.getId() == null) {17 entity.setId(nextId→ 3++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityProduct(2, Mouse, $29.99));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityProduct(2, Mouse, $29.99));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: Product id=2System.out.println(" All products: " + productRepo.findAll());
90System.out.println(" All products: " + productRepo.findAll());System.out.println(" All products: " + productRepo.findAll());
90System.out.println(" All products: " + productRepo.findAll());output All products: [Product(1, Laptop, $999.99), Product(2, Mouse, $29.99)]System.out.println(" All products: " + productRepo.findAll());
90System.out.println(" All products: " + productRepo.findAll());9192System.out.println("\nService layer:");output All products: [Product(1, Laptop, $999.99), Product(2, Mouse, $29.99)] Service layer: Service layer:this.repository ← ⟨BoundsInheritance$Repository A⟩
97public Service(Repository<T> repository⟨BoundsInheritance$Repository A⟩) {98 this.repository→ ⟨BoundsInheritance$Repository A⟩ = repository⟨BoundsInheritance$Repository A⟩;99}public T create(T entity)
101public T create(T entityUser(null, Charlie)) {102 repository.save(entity);repository.save(entity);
101public T create(T entity) {102 repository.save(entityUser(null, Charlie));103 System.out.println(" Created: " + entity);nextId ← 4
16if (entity.getId() == null) {17 entity.setId(nextId→ 4++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityUser(3, Charlie));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityUser(3, Charlie));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: User id=3entity ← User(3, Charlie)
101public T create(T entity) {102 repository.save(entity→ User(3, Charlie));103 System.out.println(" Created: " + entity);System.out.println(" Created: " + entity);
102repository.save(entity);103System.out.println(" Created: " + entityUser(3, Charlie));104return entity;System.out.println(" Created: " + entity);
102repository.save(entity);103System.out.println(" Created: " + entityUser(3, Charlie));104return entity;output Created: User(3, Charlie)return entity;
103 System.out.println(" Created: " + entity);104 return entityUser(3, Charlie);105}public T getById(Long id)
116public T getById(Long id3) {117 T entity = repository.findById(id3);118 if (entity == null) {public T findById(Long id)
24public T findById(Long id3) {25 return store.get(id3);26}entity ← User(3, Charlie)
116public T getById(Long id) {117 T entity→ User(3, Charlie) = repository.findById(id3);118 if (entity == null) {return entity;
120 }121 return entityUser(3, Charlie);122}System.out.println(" Retrieved: " + found);
127User found = userService.getById(newUser.getId());128System.out.println(" Retrieved: " + foundUser(3, Charlie));System.out.println(" Retrieved: " + found);
127User found = userService.getById(newUser.getId());128System.out.println(" Retrieved: " + foundUser(3, Charlie));output Retrieved: User(3, Charlie)System.out.println(" Retrieved: " + found);
127User found = userService.getById(newUser.getId());128System.out.println(" Retrieved: " + foundUser(3, Charlie));System.out.println(" Retrieved: " + found);
127User found = userService.getById(newUser.getId());128System.out.println(" Retrieved: " + foundUser(3, Charlie));129130System.out.println("\nAuditable entities:");output Retrieved: User(3, Charlie) Auditable entities: Auditable entities:this.product ← Laptop, this.quantity ← 1
pass 1 of 2150Order(String productLaptop, int quantity1) {151 this.product→ Laptop = productLaptop;152 this.quantity→ 1 = quantity1;153}@Override public void save(T entity)
pass 1 of 2138class AuditableRepository<T extends Auditable> extends Repository<T> {139 @Override140 public void save(T entityOrder(null, Laptop x1)) {141 super.save(entity);super.save(entity);
140public void save(T entity) {141 super.save(entityOrder(null, Laptop x1));142 System.out.println(" Created at: " + entity.getCreatedAt());nextId ← 2
16if (entity.getId() == null) {17 entity.setId(nextId→ 2++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityOrder(1, Laptop x1));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityOrder(1, Laptop x1));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: Order id=1entity ← Order(1, Laptop x1)
140public void save(T entity) {141 super.save(entity→ Order(1, Laptop x1));142 System.out.println(" Created at: " + entity.getCreatedAt());143}public long getCreatedAt()
pass 1 of 2135 public long getCreatedAt() { return createdAt1000; }136}System.out.println(" Created at: " + entity.getCreatedAt());
141 super.save(entity);142 System.out.println(" Created at: " + entity.getCreatedAt());143}output Created at: 1000this.product ← Mouse, this.quantity ← 2
pass 2 of 2150Order(String productMouse, int quantity2) {151 this.product→ Mouse = productMouse;152 this.quantity→ 2 = quantity2;153}@Override public void save(T entity)
pass 2 of 2138class AuditableRepository<T extends Auditable> extends Repository<T> {139 @Override140 public void save(T entityOrder(null, Mouse x2)) {141 super.save(entity);super.save(entity);
140public void save(T entity) {141 super.save(entityOrder(null, Mouse x2));142 System.out.println(" Created at: " + entity.getCreatedAt());nextId ← 3
16if (entity.getId() == null) {17 entity.setId(nextId→ 3++);18}store.put(entity.getId(), entity);
18}19store.put(entity.getId(), entityOrder(2, Mouse x2));20System.out.println(" Saved: " + entity.getClass().getSimpleName() +store.put(entity.getId(), entity);
18 }19 store.put(entity.getId(), entityOrder(2, Mouse x2));20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}System.out.println(" Saved: " + entity.getClass().getSimpleName() +
19 store.put(entity.getId(), entity);20 System.out.println(" Saved: " + entity.getClass().getSimpleName() + 21 " id=" + entity.getId());22}output Saved: Order id=2entity ← Order(2, Mouse x2)
140public void save(T entity) {141 super.save(entity→ Order(2, Mouse x2));142 System.out.println(" Created at: " + entity.getCreatedAt());143}public long getCreatedAt()
pass 2 of 2135 public long getCreatedAt() { return createdAt1000; }136}System.out.println(" Created at: " + entity.getCreatedAt());
141 super.save(entity);142 System.out.println(" Created at: " + entity.getCreatedAt());143}output Created at: 1000System.out.println(" Type hierarchy:");
165System.out.println("\nType hierarchy:");166167abstract class Animal {168 abstract String speak();169}170171class Dog extends Animal {172 @Override173 String speak() { return "Woof"; }174}175176class Cat extends Animal {177 @Override178 String speak() { return "Meow"; }179}180181class AnimalShelter<T extends Animal> {182 private List<T> animals = new ArrayList<>();183 184 public void add(T animal) {185 animals.add(animal);186 System.out.println(" Added: " + animal.speak());187 }188 189 public void makeAllSpeak() {190 for (T animal : animals) {191 System.out.println(" " + animal.speak());192 }193 }194}195196AnimalShelter<Dog> dogShelter = new AnimalShelter<>();197dogShelter.add(new Dog());198dogShelter.add(new Dog());output Type hierarchy: Type hierarchy:public void add(T animal)
pass 1 of 2184public void add(T animal⟨BoundsInheritance$1Dog B⟩) {185 animals.add(animal⟨BoundsInheritance$1Dog B⟩);186 System.out.println(" Added: " + animal.speak());187}System.out.println(" Added: " + animal.speak());
185 animals.add(animal);186 System.out.println(" Added: " + animal.speak());187}output Added: WoofdogShelter.add(new Dog());
196AnimalShelter<Dog> dogShelter = new AnimalShelter<>();197dogShelter.add(new Dog());198dogShelter.add(new Dog());199dogShelter.makeAllSpeak();public void add(T animal)
pass 2 of 2184public void add(T animal⟨BoundsInheritance$1Dog C⟩) {185 animals.add(animal⟨BoundsInheritance$1Dog C⟩);186 System.out.println(" Added: " + animal.speak());187}System.out.println(" Added: " + animal.speak());
185 animals.add(animal);186 System.out.println(" Added: " + animal.speak());187}output Added: WoofdogShelter.add(new Dog());
197 dogShelter.add(new Dog());198 dogShelter.add(new Dog());199 dogShelter.makeAllSpeak();200}for (T animal : animals)
pass 1 of 2189public void makeAllSpeak() {190 for (T animal⟨BoundsInheritance$1Dog B⟩ : animals⟨BoundsInheritance$1Dog[] B⟩, ⟨BoundsInheritance$1Dog C⟩]) {191 System.out.println(" " + animal.speak());192 }System.out.println(" " + animal.speak());
190for (T animal : animals) {191 System.out.println(" " + animal.speak());192}output Wooffor (T animal : animals)
pass 2 of 2189public void makeAllSpeak() {190 for (T animal⟨BoundsInheritance$1Dog C⟩ : animals⟨BoundsInheritance$1Dog[] B⟩, ⟨BoundsInheritance$1Dog C⟩]) {191 System.out.println(" " + animal.speak());192 }System.out.println(" " + animal.speak());
190for (T animal : animals) {191 System.out.println(" " + animal.speak());192}output WoofdogShelter.makeAllSpeak();
198 dogShelter.add(new Dog());199 dogShelter.makeAllSpeak();200}
Subclasses satisfy superclass bounds. Integer extends Number satisfies <T extends Number>.
Exercise: Practical.java
Build a bounded generic collection for numbers