java - generic programming
TRANSCRIPT
GENERIC PROGRAMMINGPROGRAMMAZIONE CONCORRENTE E DISTR.Università degli Studi di Padova
Dipartimento di Matematica
Corso di Laurea in Informatica, A.A. 2015 – [email protected]
2Programmazione concorrente e distribuita
SUMMARY Introduction Generic classes and methods Type variables bounds Type erasure Restrictions and limitations Generics and inheritance Wildcard types
Riccardo Cardin
3Programmazione concorrente e distribuita
INTRODUCTION Generic programming means writing code that can
be reused for object of many different typesAdded to the JDK from version 5.0
It tooks 5 years to be formalized (from 1999) First added to support strongly typed collections (as in C++)
No generic code is obscure and not typesafe
Before generics there was no typesafe checking Errors will be find only at runtime Violation of FAIL FAST principle
Riccardo Cardin
// Before generic classesArrayList files = new ArrayList();// You do not know which kind of object are store inside the listString filename = (String) files.get(0);
4Programmazione concorrente e distribuita
INTRODUCTION Generics solution: type parameters
The compiler can perform typesafe checks
Generics make the code safer and easier to read But how will you use generic programming?
Basic level: just use generic classes Intermediate level: when you encounter your first
enigmatic error using generic classesAdvanced level: implement your own generic classes
Riccardo Cardin
// After generic classesArrayList<String> files = new ArrayList<>();// You do not need the cast operation anymoreString filename = files.get(0);
5Programmazione concorrente e distribuita
INTRODUCTION
Riccardo Cardin
6Programmazione concorrente e distribuita
GENERIC CLASSES A class with one or more type variable
Type variable are introduced after class name, enclosed by angle brackets < > Type variables are used throughout the class definition
It is common to use upper case letters for type variablesA type variables is instantiated by substituting types
Generic classes act as a factory for ordinary classes
Riccardo Cardin
class Pair<T, U> { private T first; private U second; // ...}
Pair<Integer, String> pair = new Pair<>();Integer first = pair.getFirst();String second = pair.getSecond();
7Programmazione concorrente e distribuita
GENERIC METHODS Also single methods can be defined as generics
Type variable definition stands behind method’s return type
Can be placed inside both generic an ordinary classesYou can omit the type variable instantiation
But sometimes the compiler gets it wrong...
Which type is inferred by the compiler? Number!!! In C++, type parameters are after method name
This can lead to ambiguitesRiccardo Cardin
public static <T> T getMiddle(T... a) { /* ... */ }String middle = getMiddle("Riccardo", "Cardin", "Professor");
double middle = ArrayAlg.getMiddle(3.14, 1729, 0);
8Programmazione concorrente e distribuita
TYPE VARIABLES BOUNDS Rescriction of a type variable to a class that is a
subtype of an another type
Use extends keyword both for classes and interfaces It is possibile to use multiple bounds
At most one bound can be a classRiccardo Cardin
class ArrayAlg { public static <T extends Comparable> T min(T[] a) { if (a == null || a.length == 0) return null; T smallest = a[0]; for (int i = 1; i < a.length; i++) // We know for sure that compareTo is available if (smallest.compareTo(a[i]) > 0) smallest = a[i]; return smallest; } }
T extends Comparable & Serializable
9Programmazione concorrente e distribuita
TYPE ERASURE The JVM does not have objects of generic types
Type variables are erased and replaced with bounding variables or Object type if it ain’t any For each generic type a raw type is provided automatically
Casts are inserted if necessary to preserve type safetyBridge methods are generated to preserve
polymorphismNo new class are created for parametrized typesRiccardo Cardin
// Remember generic class Pair<T, U> ?class Pair { private Object first; private Object second; // ...}
10Programmazione concorrente e distribuita
TYPE ERASURE Translating generic expression
Compiler inserts casts when the return the return type has been erased
Translating generic methodsA generic method is not a family of methods
This fact has a series of implications... Riccardo Cardin
Pair<Employee, Salary> buddies = /* ... */;Employee buddy = buddies.getFirst();// After type erasure will becomePair buddies = /* ... */;Employee buddy = (Employee) buddies.getFirst(); // Returns an Object
public static <T extends Comparable> T min(T[] a)// becomes after type erasurepublic static Comparable min(Comparable[] a)
11Programmazione concorrente e distribuita
TYPE ERASURE Translating generic methods
Type erasure interferes with polymorphism, then the compiler generates synthetic bridge methods
Riccardo Cardin
public class Node<T> { public T data; public Node(T data) { this.data = data; } public void setData(T data) { System.out.println("Node.setData"); this.data = data; }}public class MyNode extends Node<Integer> { public MyNode(Integer data) { super(data); } @Override public void setData(Integer data) { System.out.println("MyNode.setData"); super.setData(data); }}
12Programmazione concorrente e distribuita
TYPE ERASURE Translating generic methods
After type erasure setData method has wrong type and cannot override parent method
Riccardo Cardin
public class Node { public Object data; public Node(Object data) { this.data = data; } public void setData(Object data) { System.out.println("Node.setData"); this.data = data; }}public class MyNode extends Node { public MyNode(Integer data) { super(data); } // Not polymorphic anymore :O public void setData(Integer data) { System.out.println("MyNode.setData"); super.setData(data); }}
13Programmazione concorrente e distribuita
TYPE ERASURE Translating generic methods
Compiler insert a bridge method that overrides the parent method, resolving subtyping Delegation design pattern
There are cases that are stanger The type parameters appears only in method return type
Riccardo Cardin
class MyNode extends Node { // Bridge method generated by the compiler public void setData(Object data) { setData((Integer) data); } // ...
class DateInterval extends Pair<Date> { public Date getSecond() { return (Date) super.getSecond().clone(); }}
Let’s try it yourself
14Programmazione concorrente e distribuita
TYPE ERASURE
Riccardo Cardin
15Programmazione concorrente e distribuita
RESTRICTIONS AND LIMITATIONS Type Parameters Cannot Be Instantiated with
Primitive Types Runtime Type Inquiry Only Works with Raw Types You Cannot Create Arrays of Parameterized Types Varargs Warnings... You Cannot Instantiate Type Variables Type Variables Are Not Valid in Static Contexts of
Generic Classes You Cannot Throw or Catch Instances of a Generic
Class Beware of Clashes after Erasure
Riccardo Cardin
16Programmazione concorrente e distribuita
GENERICS AND INHERITANCE Generics and inheritance works togheter in an
unintuitive way In general, there is no relationship between Pair<S>
and Pair<T>, no matter how S and T are related Necessary for type safety
Generics are said invariant
Riccardo Cardin
// Type safety restrictionPair<Manager> managerBuddies = new Pair<>(ceo, cfo);// Illegal, but suppose it // wasn'tPair<Employee> employeeBuddies = managerBuddies; employeeBuddies.setFirst( lowlyEmployee);
17Programmazione concorrente e distribuita
GENERICS AND INHERITANCE Unfortunately there is a way to bypass this type
safety controls
But, this is the same behaviour we obtain using older version of Java (≤ 1.5) NEVER use raw type of generics if you can
Generic classes can extend or implement other generic types For example, ArrayList<T> implements List<T>
So, an ArrayList<Manager> is subtype of List<Manager>
Riccardo Cardin
Pair<Manager> managerBuddies = new Pair<>(ceo, cfo);Pair rawBuddies = managerBuddies; // OK// Only a compile-time warning. A ClassCastException // is thrown at runtimerawBuddies.setFirst(new File(". . ."));
18Programmazione concorrente e distribuita
WILDCARD TYPES The type system derived is too rigid: wildcard
types help to safetly relax some constraint
Why using wildcard types can we force type safety? The compiler cannot guess the real type the object passed
Use wildcard type as return types in methods In return types the compiler needs only to know which is the
supertype, to allow assignments Type ? extends T is said covariant wrt type T
Riccardo Cardin
// Any generic Pair whose type parameter is a subclass of EmployeePair<? extends Employee>
Pair<Manager> managerBuddies = new Pair<>(ceo, cfo);Pair<? extends Employee> wildcardBuddies = managerBuddies; // OKwildcardBuddies.setFirst(lowlyEmployee); // compile-time error
19Programmazione concorrente e distribuita
WILDCARD TYPES
Riccardo Cardin
20Programmazione concorrente e distribuita
WILDCARD TYPES How can we use wildcard type for parameters?
In Java are available supertype bounds
A wildcard with a super type bound gives you a behavior that is opposite to that of the wildcards
You can supply parameters to methods, but you can’t use the return values
As a return values the only possible assignee type is Object Type ? super T is said contravariant wrt type T Riccardo Cardin
// Any generic Pair whose type parameter is restricted to all // supertypes of ManagerPair<? super Manager>
// Any generic Pair whose type parameter is restricted to all // supertypes of ManagerPair<? super Manager>
21Programmazione concorrente e distribuita
WILDCARD TYPES
Riccardo Cardin
22Programmazione concorrente e distribuita
WILDCARD TYPES You can even use wildcards with no bounds
As a return value, can only be assigned to an Object As a parameter, no type matches, not even Object
A method with a parameter with an unbounded wildcard type can never be called Actually, you can call it passing a null reference...
Remember, an unbounded wildcard is not a type So you can not use it when a type is requested
Riccardo Cardin
// It is different from the raw type PairPair<?>
// This code is not valid, use type variables instead? t = p.getFirst(); // ERRORp.setFirst(p.getSecond());p.setSecond(t);
23Programmazione concorrente e distribuita
WILDCARD TYPES
Riccardo Cardin
24Programmazione concorrente e distribuita
EXAMPLES
Riccardo Cardin
https://github.com/rcardin/pcd-snippets
25Programmazione concorrente e distribuita
REFERENCES Chap. 12 «Generic Programming», Core Java Volume I -
Fundamentals, Cay Horstmann, Gary Cornell, 2012, Prentice Hall Chap. 6 «Generic Programming», Core Java for the Impatient, Cay
Horstmann, 2015, Addison-Wesley Type Erasure
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html Effects of Type Erasure and Bridge Methods https://
docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html Covariance and Contravariance In Java
https://dzone.com/articles/covariance-and-contravariance Covariance, Invariance and Contravariance explained in plain
English? http://stackoverflow.com/questions/8481301/covariance-invariance-and-contravariance-explained-in-plain-english
Riccardo Cardin