-
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.
[05-generics] Add Code Snippets (#126)
* Add Generics code snippets
- Loading branch information
1 parent
eebd930
commit 5c46682
Showing
6 changed files
with
262 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,85 @@ | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
// Base class Entity | ||
abstract class Entity { | ||
private final long id; | ||
|
||
public Entity(long id) { | ||
this.id = id; | ||
} | ||
|
||
public long getId() { | ||
return id; | ||
} | ||
} | ||
|
||
// Generic Storage class for Entity | ||
class EntityStorage<T extends Entity> { | ||
private Map<Long, T> entities; | ||
|
||
public EntityStorage() { | ||
this.entities = new HashMap<>(); | ||
} | ||
|
||
public T getEntity(long id) { | ||
return entities.get(id); | ||
} | ||
|
||
public void addEntity(T entity) { | ||
this.entities.put(entity.getId(), entity); | ||
} | ||
} | ||
|
||
// Specialized Storage class for Employee | ||
class Employee extends Entity { | ||
private String name; | ||
|
||
public Employee(long id, String name) { | ||
super(id); | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
} | ||
|
||
// Specialized Storage class for EmployeeStorage with bridge method | ||
class EmployeeStorage extends EntityStorage<Employee> { | ||
public EmployeeStorage() { | ||
super(); | ||
} | ||
|
||
// Additional methods specific to EmployeeStorage | ||
public String getEmployeeName(long id) { | ||
return getEntity(id).getName(); | ||
} | ||
|
||
// Due to type erasure, the getEntity method in the EmployeeStorage class has an erased signature. | ||
// The compiler generates a bridge method in the EmployeeStorage class to ensure that the | ||
// overridden method in the EntityStorage<Employee> interface adheres to the erasure rules. | ||
// | ||
// Bridge methods are synthetic methods added by the compiler to maintain polymorphism | ||
// and type safety in the presence of type erasure. They are not directly written | ||
// in the source code but are introduced during the compilation process. | ||
@Override | ||
public Employee getEntity(long id) { | ||
return super.getEntity(id); | ||
} | ||
} | ||
|
||
public class BridgeMethodsExample { | ||
public static void main(String[] args) { | ||
Employee employee = new Employee(1, "John Doe"); | ||
|
||
EmployeeStorage employeeStorage = new EmployeeStorage(); | ||
|
||
// Access specific method | ||
System.out.println("Employee Name: " + employeeStorage.getEmployeeName(1)); | ||
|
||
// Access generic method through the bridge | ||
Entity genericEntity = employeeStorage.getEntity(1); | ||
System.out.println("Generic Entity ID: " + genericEntity.getId()); | ||
} | ||
} |
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(2022, 2023)); | ||
} | ||
|
||
} |