-
Notifications
You must be signed in to change notification settings - Fork 137
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
219 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Generics / Code snippets |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
class Box<T> { | ||
private T value; | ||
|
||
public void setValue(T value) { | ||
this.value = value; | ||
} | ||
} | ||
|
||
class BoxOfInt extends Box<Integer> { | ||
private Integer value; | ||
|
||
@Override | ||
public void setValue(Integer value) { | ||
this.value = value; | ||
} | ||
|
||
/* | ||
After type parameter erasure, the overriden setValue() method in the superclass and here | ||
would have different signatures: | ||
public void setValue(Object value) { this.value = value; } // in Box | ||
public void setValue(Integer value) { this.value = value; } // in BoxOfInt | ||
To solve this, the compiler generates a synthetic method in BoxOfInt, called a "bridge method": | ||
public void setValue(Object value) { this.value = (Integer) value; } // in BoxOfInt | ||
Bridge methods are not visible in the source code but can be seen in the resulting bytecode. | ||
Have a look disassembling it with javap -c BoxOfInt.class | ||
*/ | ||
|
||
} | ||
|
||
public class BridgeMethods { | ||
|
||
public static void main(String... args) { | ||
Box<Integer> boxOfInt = new BoxOfInt(); | ||
boxOfInt.setValue(1); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
public class Container<T extends Number> { | ||
|
||
public static void main(String[] args) { | ||
Container<Integer> ci = new Container<>(); | ||
Container<Double> cd = new Container<>(); | ||
|
||
// Container<String> cs = new Container<>(); // will not compile | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
final class Pineapple extends Fruit {} | ||
final class Melon extends Fruit {} | ||
|
||
public sealed class Fruit<T> permits Pineapple, Melon { | ||
private T t; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
public record GenericRecord<K, V>(K key, V value) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
class LivingThing { | ||
|
||
} | ||
|
||
class Human extends LivingThing { | ||
private String name; | ||
|
||
public Human(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} | ||
|
||
class Student extends Human { | ||
private int fn; | ||
|
||
public Student(String name, int fn) { | ||
super(name); | ||
this.fn = fn; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Student{" + | ||
"fn=" + fn + | ||
'}'; | ||
} | ||
} | ||
|
||
class FMIStudent extends Student { | ||
public FMIStudent(String name, int fn) { | ||
super(name, fn); | ||
} | ||
|
||
} | ||
|
||
public class GenericsPlayground { | ||
|
||
// The Get & Put principle in action | ||
|
||
private static void getHumans(List<? extends Human> listOfHumans) { | ||
|
||
// we can safely get, and we can rely on always getting a Human | ||
for (Human h : listOfHumans) { // we can safely iterate as Human and call methods of Human | ||
System.out.println(h.getName()); | ||
} | ||
|
||
// we can only put null | ||
listOfHumans.add(null); | ||
|
||
} | ||
|
||
private static void putHumans(List<? super Human> listOfSuperHumans) { | ||
|
||
// we can safely put instances of Human and successors of Human | ||
listOfSuperHumans.add(new Student("Georgi Todorov", 62348)); | ||
listOfSuperHumans.add(new Human("Anelia Angelova")); | ||
listOfSuperHumans.add(new FMIStudent("Zahari Zvezdomirov", 62216)); | ||
// listOfSuperHumans.add(new LivingThing()); // will not compile, why? | ||
|
||
// if we get, we can just rely on getting a java.lang.Object | ||
Object o = listOfSuperHumans.get(0); | ||
if (o instanceof Student) { | ||
System.out.println(((Student) o).getName()); | ||
} | ||
System.out.println(o); | ||
|
||
} | ||
|
||
private static int neitherGetNorPut(List<?> listOfUnknown) { | ||
|
||
// if we get, we can just rely on getting a java.lang.Object | ||
Object o = listOfUnknown.get(0); | ||
|
||
// we can only put null | ||
listOfUnknown.add(null); | ||
// listOfUnknown.add("kuku"); // will not compile | ||
|
||
// we can use only methods that are agnostic to the type of elements | ||
return listOfUnknown.size(); | ||
|
||
} | ||
|
||
public static void main(String[] args) { | ||
|
||
List<FMIStudent> listOfFMIStudents = new ArrayList<>(); | ||
List<Student> listOfStudents = new ArrayList<>(); | ||
List<Human> listOfHumans = new ArrayList<>(); | ||
List<LivingThing> listOfLivingThings = new ArrayList<>(); | ||
List<Object> listOfObjects = new ArrayList<>(); | ||
|
||
getHumans(listOfHumans); | ||
getHumans(listOfStudents); | ||
getHumans(listOfFMIStudents); | ||
|
||
putHumans(listOfHumans); | ||
putHumans(listOfLivingThings); | ||
putHumans(listOfObjects); | ||
|
||
System.out.println(neitherGetNorPut(new ArrayList<>(List.of(1, 2, 3)))); // 4 | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
public class Pair<K, V> { | ||
|
||
private K key; | ||
private V value; | ||
|
||
public Pair(K key, V value) { | ||
this.key = key; | ||
this.value = value; | ||
} | ||
|
||
public K getKey() { | ||
return key; | ||
} | ||
|
||
public void setKey(K key) { | ||
this.key = key; | ||
} | ||
|
||
public V getValue() { | ||
return value; | ||
} | ||
|
||
public void setValue(V value) { | ||
this.value = value; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Pair{" + | ||
"key=" + key + | ||
", value=" + value + | ||
'}'; | ||
} | ||
|
||
public static void main(String[] args) { | ||
Pair<String, Integer> pair1 = new Pair<>("Stoyo", 1); | ||
Pair<String, Integer> pair2 = new Pair<>("Boyo", 6); | ||
|
||
Pair<Double, Double> pair3 = new Pair<>(1.0, 1.0); | ||
|
||
Pair<List<String>, Set<Integer>> pair4 = new Pair<>(List.of("FMI", "rulez"), Set.of(2024, 2025)); | ||
} | ||
|
||
} |