Genericos en Java
Genericos en Java
Generics
Yann-Gaël Guéhéneuc
[Link]@[Link]
Version 1.1
2014/05/12
2/171
2013/03/22 – v1.0 – First version of the slides
2013/04/19 – v1.0.1 – Fixed some typos
2014/05/12 – v1.1 – Added example of mixing objects
Cited PECS explanations
Added more generated bytecodes
Fixed some typos
3/171
Problem
import [Link];
4/171
Problem
5/171
Problem
Sorting
lists assumes (and is sure) that the
elements stored in the list are comparable
import [Link];
6/171
Outline
Parametric polymorphism
– Expressiveness
– Type-safety
• First implementation in ML in 1989 (1976?)
Robin Milner, Robert Harper, David MacQueen, and Mads Tofte ; “The Definition Of Standard
ML” ; The MIT Press, 1997. 10/171
Explicit parametric
History polymorphism
Parametric polymorphism
– Expressiveness
– Type-safety
• First implementation in ML in 1989 (1976?)
Robin Milner, Robert Harper, David MacQueen, and Mads Tofte ; “The Definition Of Standard
ML” ; The MIT Press, 1997. 11/171
History
David Musser Alexander Stepanov
*c.1945 *1950
—Alexander Stepanov
13/171
History
Generic programming
– Theory of iterators
– Independent of implementation
• C++ Standard Template Library (STL)
[Link] 18/171
Problem
import [Link];
19/171
Problem
20/171
Problem
import [Link];
21/171
Outline
package [Link];
[Link]([Link]);
[Link]([Link]);
[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);
[Link]([Link]());
[Link]([Link]());
}
}
23/171
Special Case
24/171
Special Case
25/171
Special Case
26/171
New concrete type
Special Case (pseudo-type in Java)
Every new array instantiates a new concrete
type (or reuse an existing concrete type)
27/171
Special Case
[Link]([Link]);
[Link]([Link]);
[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);
[Link]([Link]());
[Link]([Link]());
28/171
Pseudo-field
Special Case
[Link]([Link]);
[Link]([Link]);
[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);
[Link]([Link]());
[Link]([Link]());
29/171
Pseudo-field
Special Case
Access, a[b]
Syntax and semantics built in the compiler
[Link]([Link]);
[Link]([Link]);
[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);
[Link]([Link]());
[Link]([Link]());
30/171
Pseudo-field
Special Case
Access, a[b]
In the Java programming language
Syntax and semantics built in the compiler
arrays are objects (§4.3.1), are
dynamically created, and may be
assigned to variables of type Object
(§4.3.2). All methods of class Object
may be invoked on an array.
—JLS
[Link]([Link]);
[Link]([Link]);
[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);
[Link]([Link]());
[Link]([Link]());
31/171
Outline
Polymorphism
– Ad-hoc polymorphism
– Subtype polymorphism
– Parametric polymorphism
• Implicit
• Explicit
33/171
General Definitions
Ad-hoc polymorphism
– Method overloading
– Not a feature of the type system
– Dispatch mechanism
• Typically, dispatch depends on the concrete type of
the receiver of a method
Ad-hoc polymorphism
– A name may have more than one meaning
• It may refer to more than one algorithm
– The choice of the algorithm is context-
dependent but know at compile-time
(Early binding when compared to the following
subtype polymorphism)
35/171
General Definitions
Barbara Liskov
*1939
Subtype polymorphism
– Liskov substitution principle
36/171
General Definitions
Subtype polymorphism
package [Link];
import [Link];
import [Link];
o = new Long(1);
[Link]([Link]());
o = new Frame();
[Link]([Link]());
}
}
37/171
Declared type vs.
General Definitions concrete types
Subtype polymorphism
package [Link];
import [Link];
import [Link];
o = new Long(1);
[Link]([Link]());
o = new Frame();
[Link]([Link]());
}
}
38/171
General Definitions
Parametric polymorphism
public class NonGenericBox {
private Object object;
39/171
Must cast to ask
General Definitions compiler to allow
the assignment
Parametric polymorphism
public class NonGenericBox {
private Object object;
40/171
General Definitions
Parametric polymorphism
public class NonGenericBox {
private Object object;
41/171
Legal!
General Definitions
Parametric polymorphism
public class NonGenericBox {
private Object object;
42/171
General Definitions
Parametric polymorphism
Parametric polymorphism
Parametric polymorphism
Parametric polymorphism
public class GenericBox<T> {
private T t;
49/171
General Definitions
Parametric polymorphism
public class GenericBox<T> {
private T t;
50/171
Illegal!
General Definitions
Parametric polymorphism
public class GenericBox<T> {
private T t;
51/171
General Definitions
Parametric polymorphism
package [Link];
52/171
General Definitions
Parametric polymorphism
package [Link];
Parametric polymorphism
package [Link];
Parametric polymorphism
package [Link];
57/171
Generics Definitions
Java
generics are one implementation of
parametric polymorphism
– Type erasure
Parametric polymorphism
– Predicative
• ML
– Impredicative
• System F
• C++, Java 1.5
– Bounded
• C++ in one way, Java 1.5 in another
Martín Abadi, Luca Cardelli, Pierre-Louis Curien ; “Formal Parametric Polymorphism” ; SRC
research report, issue 109, Digital, Systems Research Center, 1993. 60/171
Generics Definitions
61/171
Generics Definitions
62/171
Generics Definitions
63/171
Generics Definitions
– Example 2
64/171
Generics Definitions
– Example 2
65/171
Generics Definitions
– Example 2
import [Link];
66/171
Generics Definitions
67/171
Generics Definitions
[Link] 68/171
Generics Definitions
public class Example5 {
public static void main(final String[] args) {
final Sort<A> sort = new Sort<A>();
final List<A> listOfAs = new ArrayList<A>();
[Link](listOfAs);
[Link]();
}
}
class Sort<E extends Comparable<E>> {
public List<E> sort(final List<E> aList) {
return // TO DO
}
}
class A implements Comparable<A> {
public int compareTo(final A o) {
return // TO DO
}
}
class B implements Comparable<B> {
public int compareTo(final B o) {
return // TO DO
}
}
69/171
Generics Definitions
public class Example5 {
public static void main(final String[] args) {
final Sort<A> sort = new Sort<A>();
final List<A> listOfAs = new ArrayList<A>();
[Link](listOfAs);
[Link]();
}
}
class Sort<E extends Comparable<E>> {
public List<E> sort(final List<E> aList) {
return // TO DO
}
}
class A implements Comparable<A> {
public int compareTo(final A o) {
return // TO DO
}
}
class B implements Comparable<B> {
public int compareTo(final B o) {
return // TO DO
}
}
Java
C++
72/171
Generics Definitions
[Link] 73/171
Generics Definitions class X {
public:
virtual void kewl_method() { /* etc. */ }
};
class Y: public X {
public:
virtual void kewl_method() { /* etc. */ }
};
class Z {
public:
virtual void kewl_method() { /* etc. */ }
};
class K {
public:
virtual void wazaa() { /* etc. */ }
};
template<typename T>
class A {
public:
void foo() {
T t;
t.kewl_method();
}
};
74/171
Generics Definitions class X {
public:
virtual void kewl_method() { /* etc. */ }
};
class Y: public X {
public:
virtual void kewl_method() { /* etc. */ }
};
class Z {
public:
virtual void kewl_method() { /* etc. */ }
};
class K {
public:
virtual void wazaa() { /* etc. */ }
};
template<typename T>
class A {
public:
void foo() {
T t;
t.kewl_method();
}
};
template<typename T>
class A {
public:
void foo() {
T t;
}
t.kewl_method(); Common API
};
76/171
Generics Definitions
int main()
{
// A's constraint is : implements kewl_method
A<X> x ; [Link]() ;
// OK: x implements kewl_method
A<Y> y ; [Link]() ;
// OK: y derives from X
A<Z> z ; [Link]() ;
// OK: z implements kewl_method
A<K> k ; [Link]() ;
// NOT OK : K won't compile: /[Link] error:
// ‘class K’ has no member named ‘kewl_method’
return 0;
}
77/171
Generics Definitions
int main()
{
// A's constraint is : implements kewl_method
A<X> x ; [Link]() ;
// OK: x implements kewl_method
A<Y> y ; [Link]() ;
// OK: y derives from X
A<Z> z ; [Link]() ;
// OK: z implements kewl_method
A<K> k ; [Link]() ;
// NOT OK : K won't compile: /[Link] error:
// ‘class K’ has no member named ‘kewl_method’
return 0;
}
Duck typing
– Dynamically-typed languages: Smalltalk
– Statically-typed language: C++
80/171
Generics Definitions
D1 compile: 'foo
Transcript show: ''D1'' ; cr.'.
D2 compile: 'foo
Transcript show: ''D2'' ; cr.'.
82/171
Generics Definitions
D1 compile: 'foo
Transcript show: ''D1'' ; cr.'.
D2 compile: 'foo
Transcript show: ''D2'' ; cr.'.
Two unrelated
classes 83/171
Generics Definitions
d := D new.
d needAFooMethod: (D1 new).
d needAFooMethod: (D2 new).
D1
D2
84/171
Outline
86/171
When to Use Generics
import [Link];
87/171
Outline
Lots of resources
Lots of discussions
90/171
How to Use Generics
91/171
How to Use Generics
92/171
How to Use Generics
93/171
How to Use Generics
95/171
How to Use Generics
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
Object nextElement();
}
97/171
How to Use Generics
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
Object nextElement();
}
98/171
Forces clients
How to Use Generics to use Object
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
Object nextElement();
}
99/171
How to Use Generics
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
Object nextElement();
}
100/171
Clients must know the
How to Use Generics
type of the next element
Family of algorithms, another look
public interface Enumeration {
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
boolean hasMoreElements();
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
Object nextElement();
}
101/171
How to Use Generics
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
E nextElement();
}
102/171
How to Use Generics
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
E nextElement();
}
103/171
Clients can specify the
How to Use Generics
type of the next element
Family of algorithms, solution
public interface Enumeration<E> {
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
boolean hasMoreElements();
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
E nextElement();
}
104/171
Outline
106/171
Caveats with Generics
107/171
Caveats with Generics
108/171
Caveats with Generics
[Link](1);
[Link](new Integer(1));
[Link]([Link]());
}
}
109/171
Autoboxing from
Caveats with Generics
int to Integer
ints and Integers, what happens?
import [Link];
import [Link];
[Link](1);
[Link](new Integer(1));
[Link]([Link]());
}
}
110/171
Exact parameter Autoboxing from
Caveats with
matching takesGenerics
int to Integer
over autoboxing
ints and Integers, what happens?
import [Link];
import [Link];
[Link](1);
[Link](new Integer(1));
[Link]([Link]());
}
}
111/171
Exact parameter Autoboxing from
Caveats with
matching takesGenerics
int to Integer
over autoboxing
ints and Integers, what happens?
import [Link];
import [Link];
[Link](1);
[Link](new Integer(1));
}
}
[Link]([Link]());
0
112/171
Caveats with Generics
import [Link];
[Link]
java-how-to-use-clone-and-what-about-the-cast-check 113/171
No complains
Caveats with Genericsfor the compiler
import [Link];
[Link]
java-how-to-use-clone-and-what-about-the-cast-check 114/171
Caveats with Generics
import [Link];
115/171
Caveats with Generics
import [Link];
116/171
Type safety: Unchecked cast from
Caveats to
Object with Generics
ArrayList<Integer>
Use of clone(), now
import [Link];
117/171
Caveats with Generics
118/171
Caveats with Generics
@SuppressWarnings("unchecked")
final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();
[Link](list2);
}
}
121/171
Caveats with Generics
@SuppressWarnings("unchecked")
final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();
[Link](list2);
}
}
123/171
Cannot instantiate
Caveats with Generics
the type T
Instantiating a type variable, problem
public class InstantiatingTypeParameterProblem<T> {
public static void main(final String[] args) {
...
}
public T getInstanceOfT (){
// Neither lines work:
return new T();
return [Link]();
}
...
}
124/171
Cannot instantiate
Caveats with Generics
the type T
Instantiating a type variable, problem
public class InstantiatingTypeParameterProblem<T> {
public static void main(final String[] args) {
...
}
public T getInstanceOfT (){
// Neither lines work:
return new T();
return [Link]();
}
...
}
126/171
Caveats with Generics
127/171
Caveats with Generics
129/171
Type argument
Caveats with Generics and subclassing
130/171
Caveats with Generics
131/171
The superclass is generic,
Caveats withthe
Generics
subclass specialises it
Instantiating a type variable, solution #3
– Prevent type erasure by specialising an
interesting class
import [Link];
132/171
Caveats with Generics
133/171
Caveats with Generics
Multiple bounds
Multiple bounds
class Example8A {
}
interface Example8B {
}
interface Example8C {
}
class Example8D<T extends Example8A & Example8B & Example8C> {
}
class Example8Test1 extends Example8A implements Example8B, Example8C {
}
class Example8Test2 extends Example8A {
}
public class Example8 {
public static void main(final String[] args) {
final Example8D<Example8Test1> d1 = new Example8D<Example8Test1>();
final Example8D<Example8Test2> d2 = new Example8D<Example8Test2>();
}
}
136/171
Bound mismatch: The type Test2 is
Caveats
not a validwith Generics
substitute for the bounded
parameter <T extends …>
Multiple bounds
class Example8A {
}
interface Example8B {
}
interface Example8C {
}
class Example8D<T extends Example8A & Example8B & Example8C> {
}
class Example8Test1 extends Example8A implements Example8B, Example8C {
}
class Example8Test2 extends Example8A {
}
public class Example8 {
public static void main(final String[] args) {
final Example8D<Example8Test1> d1 = new Example8D<Example8Test1>();
final Example8D<Example8Test2> d2 = new Example8D<Example8Test2>();
}
}
137/171
Caveats with Generics
import [Link];
138/171
Caveats with Generics
PECS
– Collections that produce extends
– Collections that consume super
[Link] 139/171
Caveats with Generics
PECS
– Collections that produce extends
• They produce elements of some types
• These types must be “topped” to tell the client that it
can safely expect to receive Somthing
• Any item from the collection is a Somthing (in the
sense of Liskov’s substitution)
140/171
Caveats with Generics
PECS
– Collections that consume super
• They consume elements of some types
• These types must be “bottomed” to tell the client that
it can safely put Something
• Any item in the collection is “at most” Something (in
the sense of Liskov’s substitution)
141/171
Caveats with Generics
PECS
Another way to remember the producer /
consumer distinction is to think of a method
signature. If you have a method
useList(List), you are consuming the List
and so need covariance / extends. If your
method is List buildList(), then you are
producing the List and will need
contravariance / super
—Adapted from Raman
[Link] 142/171
Caveats with Generics
PECS
– Collections that produce and consume must just
use one type parameter
• Not legal to combine extends and super
Collection<Something>
143/171
Caveats with Generics
[Link] 144/171
Legality depends on compiler
Caveats with Generics
• Eclipse 3.5 says yes
• Eclipse 3.6 says no
• Intellij 9 says yes
• Sun javac 1.6.0_20 says yes
• GCJ 4.4.3 says yes
• GWT compiler says yes
• Crowd says no
[Link] 145/171
Outline
class Example11A {
}
public class Example11 {
public static void main(final String[] args) {
final Example11A anA1 = new Example11A();
final Class<Example11A> anA1Class =
(Class<Example11A>) [Link]();
[Link](anA1Class);
[Link]
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 148/171
Type safety: Unchecked cast from
Caveats with Generics
Class<capture#1-of ?
extends Example11A> to
Type-safe use of getClass()
Class<Example11A>
class Example11A {
}
public class Example11 {
public static void main(final String[] args) {
final Example11A anA1 = new Example11A();
final Class<Example11A> anA1Class =
(Class<Example11A>) [Link]();
[Link](anA1Class);
[Link]
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 149/171
Type safety: Unchecked cast from
Caveats with Generics
Class<capture#1-of ?
extends Example11A> to
Type-safe use of getClass()
Class<Example11A>
class Example11A {
}
public class Example11 {
public static void main(final String[] args) {
final Example11A anA1 = new Example11A();
final Class<Example11A> anA1Class =
(Class<Example11A>) [Link]();
[Link](anA1Class);
[Link]
No warning
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 150/171
Caveats with Generics
[Link]
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 151/171
Type safety: Unchecked cast from
Caveats with Generics ? extends
Class<capture#4-of
List> to Class<List<Integer>>
Type-safe use of getClass()
[Link]
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 152/171
Type safety: Unchecked cast from
Caveats with Generics ? extends
Class<capture#4-of
List> to Class<List<Integer>>
Type-safe use of getClass()
[Link]
No warning
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 153/171
Caveats with Generics
Use of newInstance()
class Example10A {
}
public class Example10 {
public static void main(final String[] args) {
final Class<Example10A> clazz1 = [Link];
final Example10A anA1 = [Link]();
[Link](anA1);
[Link] 154/171
Caveats with Generics
[Link]
get-type-of-a-generic-parameter-in-java-with-reflection 155/171
Caveats with Generics
156/171
Caveats with Generics
157/171
Caveats with Generics
158/171
Caveats with Generics
159/171
Caveats with Generics
160/171
Caveats with Generics
161/171
Anonymous/local class
Caveats with Generics
stores types information
Obtaining the type of a type parameter
162/171
Caveats with Generics
163/171
Caveats with Generics
164/171
Caveats with Generics
...
...
}
165/171
Outline
Java generics
167/171
Conclusion
168/171
Conclusion
169/171
Outline
171/171