KEMBAR78
Java - Generic programming | PPTX
GENERIC PROGRAMMING
PROGRAMMAZIONE CONCORRENTE E DISTR.
Università degli Studi di Padova
Dipartimento di Matematica
Corso di Laurea in Informatica, A.A. 2015 – 2016
rcardin@math.unipd.it
Programmazione concorrente e distribuita
SUMMARY
 Introduction
 Generic classes and methods
 Type variables bounds
 Type erasure
 Restrictions and limitations
 Generics and inheritance
 Wildcard types
2Riccardo Cardin
Programmazione concorrente e distribuita
INTRODUCTION
 Generic programming means writing code that
can be reused for object of many different types
 Added 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
3Riccardo Cardin
// Before generic classes
ArrayList files = new ArrayList();
// You do not know which kind of object are store inside the list
String filename = (String) files.get(0);
Programmazione 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 classes
 Advanced level: implement your own generic classes
4Riccardo Cardin
// After generic classes
ArrayList<String> files = new ArrayList<>();
// You do not need the cast operation anymore
String filename = files.get(0);
Programmazione concorrente e distribuita
INTRODUCTION
5Riccardo Cardin
Programmazione 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 variables
 A type variables is instantiated by substituting types
 Generic classes act as a factory for ordinary classes
6Riccardo 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();
Programmazione 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 classes
 You 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 ambiguites
7Riccardo Cardin
public static <T> T getMiddle(T... a) { /* ... */ }
String middle = getMiddle("Riccardo", "Cardin", "Professor");
double middle = ArrayAlg.getMiddle(3.14, 1729, 0);
Programmazione 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 class
8Riccardo 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
Programmazione 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 safety
 Bridge methods are generated to preserve
polymorphism
 No new class are created for parametrized types
9Riccardo Cardin
// Remember generic class Pair<T, U> ?
class Pair {
private Object first;
private Object second;
// ...
}
Programmazione concorrente e distribuita
TYPE ERASURE
 Translating generic expression
 Compiler inserts casts when the return the return
type has been erased
 Translating generic methods
 A generic method is not a family of methods
 This fact has a series of implications...
10Riccardo Cardin
Pair<Employee, Salary> buddies = /* ... */;
Employee buddy = buddies.getFirst();
// After type erasure will become
Pair buddies = /* ... */;
Employee buddy = (Employee) buddies.getFirst(); // Returns an Object
public static <T extends Comparable> T min(T[] a)
// becomes after type erasure
public static Comparable min(Comparable[] a)
Programmazione concorrente e distribuita
TYPE ERASURE
 Translating generic methods
 Type erasure interferes with polymorphism, then the
compiler generates synthetic bridge methods
11Riccardo 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);
}
}
Programmazione concorrente e distribuita
TYPE ERASURE
 Translating generic methods
 After type erasure setData method has wrong type
and cannot override parent method
12Riccardo 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);
}
}
Programmazione 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
13Riccardo 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
Programmazione concorrente e distribuita
TYPE ERASURE
14Riccardo Cardin
Programmazione 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
15Riccardo Cardin
Programmazione 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
16Riccardo Cardin
// Type safety restriction
Pair<Manager> managerBuddies =
new Pair<>(ceo, cfo);
// Illegal, but suppose it
// wasn't
Pair<Employee> employeeBuddies =
managerBuddies;
employeeBuddies.setFirst(
lowlyEmployee);
Programmazione 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>
17Riccardo Cardin
Pair<Manager> managerBuddies = new Pair<>(ceo, cfo);
Pair rawBuddies = managerBuddies; // OK
// Only a compile-time warning. A ClassCastException
// is thrown at runtime
rawBuddies.setFirst(new File(". . ."));
Programmazione 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
18Riccardo Cardin
// Any generic Pair whose type parameter is a subclass of Employee
Pair<? extends Employee>
Pair<Manager> managerBuddies = new Pair<>(ceo, cfo);
Pair<? extends Employee> wildcardBuddies = managerBuddies; // OK
wildcardBuddies.setFirst(lowlyEmployee); // compile-time error
Programmazione concorrente e distribuita
WILDCARD TYPES
19Riccardo Cardin
Programmazione 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
20Riccardo Cardin
// Any generic Pair whose type parameter is restricted to all
// supertypes of Manager
Pair<? super Manager>
// Any generic Pair whose type parameter is restricted to all
// supertypes of Manager
Pair<? super Manager>
Programmazione concorrente e distribuita
WILDCARD TYPES
21Riccardo Cardin
Programmazione 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
22Riccardo Cardin
// It is different from the raw type Pair
Pair<?>
// This code is not valid, use type variables instead
? t = p.getFirst(); // ERROR
p.setFirst(p.getSecond());
p.setSecond(t);
Programmazione concorrente e distribuita
WILDCARD TYPES
23Riccardo Cardin
Programmazione concorrente e distribuita
EXAMPLES
24Riccardo Cardin
https://github.com/rcardin/pcd-snippets
Programmazione 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/bridgeMetho
ds.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
25Riccardo Cardin

Java - Generic programming

  • 1.
    GENERIC PROGRAMMING PROGRAMMAZIONE CONCORRENTEE DISTR. Università degli Studi di Padova Dipartimento di Matematica Corso di Laurea in Informatica, A.A. 2015 – 2016 rcardin@math.unipd.it
  • 2.
    Programmazione concorrente edistribuita SUMMARY  Introduction  Generic classes and methods  Type variables bounds  Type erasure  Restrictions and limitations  Generics and inheritance  Wildcard types 2Riccardo Cardin
  • 3.
    Programmazione concorrente edistribuita INTRODUCTION  Generic programming means writing code that can be reused for object of many different types  Added 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 3Riccardo Cardin // Before generic classes ArrayList files = new ArrayList(); // You do not know which kind of object are store inside the list String filename = (String) files.get(0);
  • 4.
    Programmazione concorrente edistribuita 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 classes  Advanced level: implement your own generic classes 4Riccardo Cardin // After generic classes ArrayList<String> files = new ArrayList<>(); // You do not need the cast operation anymore String filename = files.get(0);
  • 5.
    Programmazione concorrente edistribuita INTRODUCTION 5Riccardo Cardin
  • 6.
    Programmazione concorrente edistribuita 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 variables  A type variables is instantiated by substituting types  Generic classes act as a factory for ordinary classes 6Riccardo 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();
  • 7.
    Programmazione concorrente edistribuita 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 classes  You 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 ambiguites 7Riccardo Cardin public static <T> T getMiddle(T... a) { /* ... */ } String middle = getMiddle("Riccardo", "Cardin", "Professor"); double middle = ArrayAlg.getMiddle(3.14, 1729, 0);
  • 8.
    Programmazione concorrente edistribuita 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 class 8Riccardo 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
  • 9.
    Programmazione concorrente edistribuita 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 safety  Bridge methods are generated to preserve polymorphism  No new class are created for parametrized types 9Riccardo Cardin // Remember generic class Pair<T, U> ? class Pair { private Object first; private Object second; // ... }
  • 10.
    Programmazione concorrente edistribuita TYPE ERASURE  Translating generic expression  Compiler inserts casts when the return the return type has been erased  Translating generic methods  A generic method is not a family of methods  This fact has a series of implications... 10Riccardo Cardin Pair<Employee, Salary> buddies = /* ... */; Employee buddy = buddies.getFirst(); // After type erasure will become Pair buddies = /* ... */; Employee buddy = (Employee) buddies.getFirst(); // Returns an Object public static <T extends Comparable> T min(T[] a) // becomes after type erasure public static Comparable min(Comparable[] a)
  • 11.
    Programmazione concorrente edistribuita TYPE ERASURE  Translating generic methods  Type erasure interferes with polymorphism, then the compiler generates synthetic bridge methods 11Riccardo 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); } }
  • 12.
    Programmazione concorrente edistribuita TYPE ERASURE  Translating generic methods  After type erasure setData method has wrong type and cannot override parent method 12Riccardo 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); } }
  • 13.
    Programmazione concorrente edistribuita 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 13Riccardo 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
  • 14.
    Programmazione concorrente edistribuita TYPE ERASURE 14Riccardo Cardin
  • 15.
    Programmazione concorrente edistribuita 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 15Riccardo Cardin
  • 16.
    Programmazione concorrente edistribuita 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 16Riccardo Cardin // Type safety restriction Pair<Manager> managerBuddies = new Pair<>(ceo, cfo); // Illegal, but suppose it // wasn't Pair<Employee> employeeBuddies = managerBuddies; employeeBuddies.setFirst( lowlyEmployee);
  • 17.
    Programmazione concorrente edistribuita 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> 17Riccardo Cardin Pair<Manager> managerBuddies = new Pair<>(ceo, cfo); Pair rawBuddies = managerBuddies; // OK // Only a compile-time warning. A ClassCastException // is thrown at runtime rawBuddies.setFirst(new File(". . ."));
  • 18.
    Programmazione concorrente edistribuita 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 18Riccardo Cardin // Any generic Pair whose type parameter is a subclass of Employee Pair<? extends Employee> Pair<Manager> managerBuddies = new Pair<>(ceo, cfo); Pair<? extends Employee> wildcardBuddies = managerBuddies; // OK wildcardBuddies.setFirst(lowlyEmployee); // compile-time error
  • 19.
    Programmazione concorrente edistribuita WILDCARD TYPES 19Riccardo Cardin
  • 20.
    Programmazione concorrente edistribuita 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 20Riccardo Cardin // Any generic Pair whose type parameter is restricted to all // supertypes of Manager Pair<? super Manager> // Any generic Pair whose type parameter is restricted to all // supertypes of Manager Pair<? super Manager>
  • 21.
    Programmazione concorrente edistribuita WILDCARD TYPES 21Riccardo Cardin
  • 22.
    Programmazione concorrente edistribuita 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 22Riccardo Cardin // It is different from the raw type Pair Pair<?> // This code is not valid, use type variables instead ? t = p.getFirst(); // ERROR p.setFirst(p.getSecond()); p.setSecond(t);
  • 23.
    Programmazione concorrente edistribuita WILDCARD TYPES 23Riccardo Cardin
  • 24.
    Programmazione concorrente edistribuita EXAMPLES 24Riccardo Cardin https://github.com/rcardin/pcd-snippets
  • 25.
    Programmazione concorrente edistribuita 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/bridgeMetho ds.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 25Riccardo Cardin