0% found this document useful (0 votes)
6 views171 pages

Genericos en Java

The document discusses Java Generics, highlighting the importance of generic typing for sorting lists without depending on the element types. It outlines the history and definitions of parametric polymorphism, ad-hoc polymorphism, and subtype polymorphism, emphasizing their roles in type safety and expressiveness. Additionally, it provides examples and caveats related to using generics in Java programming.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views171 pages

Genericos en Java

The document discusses Java Generics, highlighting the importance of generic typing for sorting lists without depending on the element types. It outlines the history and definitions of parametric polymorphism, ad-hoc polymorphism, and subtype polymorphism, emphasizing their roles in type safety and expressiveness. Additionally, it provides examples and caveats related to using generics in Java programming.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Java

Generics
Yann-Gaël Guéhéneuc
[Link]@[Link]
Version 1.1
2014/05/12

This work is licensed under a Creative


Commons Attribution-NonCommercial-
Département de génie informatique et de génie logiciel ShareAlike 3.0 Unported License
Any questions/comments are welcome at
[Link]@[Link]
Source code available at
[Link]

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

 Sortinglists does not and should not depend


on the type of the elements stored in the list

import [Link];

public interface ISort {


public List sort(final List aList);
}

4/171
Problem

 Sortinglists does not and should not depend


on the type of the elements stored in the list

Problem: elements may not be comparable


Solution: generic typing with Comparable

5/171
Problem

 Sorting
lists assumes (and is sure) that the
elements stored in the list are comparable

import [Link];

public interface ISort<E extends Comparable<E>> {


public List<E> sort(final List<E> aList);
}

6/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
7/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
8/171
History
John C. Reynolds
*1935

 1983: Reynolds formalises the parametricity


theorem, called abstraction theorem
– Functions with similar types have similar
properties

John C. Reynolds ; “Types, abstraction, and parametric polymorphism” ; Information


Processing ; pp. 513–523, North Holland, 1983. 9/171
History

 Parametric polymorphism

append: [a]  [a]  [a]

– 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

append: [a]  [a]  [a]

– 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

 1988: David Musser and Alexander


Stepanov define the concept of generic
programming
– Abstractions from examples of algorithms and
data structure
– Concept of “concept”

David R. Musser and Alexander A. Stepanov ; “Generic Programming” ; International


symposium on Symbolic and Algebraic Computation, pp. 13-25, ACM Press, 1988. 12/171
History

“Generic programming is about abstracting


and classifying algorithms and data
structures. […] Its goal is the incremental
construction of systematic catalogs of useful,
efficient and abstract algorithms and data
structures.”

—Alexander Stepanov

13/171
History

 Generic programming
– Theory of iterators
– Independent of implementation
• C++ Standard Template Library (STL)

const ::std::vector<Foo>::iterator theEnd = [Link]();


for ( ::std::vector<Foo>::iterator i = [Link]();
i != theEnd;
++i ) {
Foo &cur_element = *i;
// Do something…
}
14/171
History

 1994: the GoF defines parameterized types

“Also known as generics (Ada, Eiffel) and


templates (C++)”

“A type that leaves some constituent types


unspecified. The unspecified types are supplied
as parameters at the point of use.”
15/171
History  19771980: Ada
– 2005: generic container library
 1985: Eiffel
Bertrand Meyer ; Object-Oriented Software
Construction ; Prentice Hall, 1988.
 1991: C++
[Link]
– 1994: STL (under Stepanov’s guidance)
 2004: Java
– Type erasure
 2005: C#
– Reified generics
16/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
17/171
Problem

“Implement generic algorithms that work on


a collection of different types”

—The Java Tutorials, Oracle

[Link] 18/171
Problem

 Sortinglists does not and should not depend


on the type of the elements stored in the list

import [Link];

public interface ISort {


public List sort(final List aList);
}

19/171
Problem

 Sortinglists does not and should not depend


on the type of the elements stored in the list

Problem: elements may not be comparable


Solution: generic typing with Comparable

20/171
Problem

 Sortinglists does not and should not depend


on the type of the elements stored in the list

import [Link];

public interface ISort<E extends Comparable<E>> {


public List<E> sort(final List<E> aList);
}

21/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
22/171
Special Case

package [Link];

public class Example1 {


public static void main(final String[] args) {
final Object[] arrayOfObjects = new Object[10];
final String[] arrayOfStrings = new String[20];

[Link]([Link]);
[Link]([Link]);

[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);

[Link]([Link]());
[Link]([Link]());
}
}

23/171
Special Case

 Array are (often) predefined generic types


final Object[] arrayOfObjects = new Object[10];
final String[] arrayOfStrings = new String[20];

24/171
Special Case

 Array are (often) predefined generic types


final Object[] arrayOfObjects = new Object[10];
final String[] arrayOfStrings = new String[20];

Any type can go here

25/171
Special Case

 Every new array instantiates a new concrete


type (or reuse an existing concrete type)

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

 Syntax and semantics built in the compiler

[Link]([Link]);
[Link]([Link]);

[Link](arrayOfObjects[0]);
[Link](arrayOfStrings[2]);

[Link]([Link]());
[Link]([Link]());

28/171
Pseudo-field
Special Case

 Syntax and semantics built in the compiler

[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

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
32/171
General Definitions

 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

Christopher Strachey ; “Fundamental Concepts in Programming Languages” ; Higher-Order and


Symbolic Computation, volume 13, issue 1-2, pp. 11-49, Springer, 2000. 34/171
General Definitions

 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

• Let q(x) be a property provable about objects x


of type T. Then q(y) should be true for objects y
of type S where S is a subtype of T

(Late binding when compared to the previous


ad hoc polymorphism)

36/171
General Definitions

 Subtype polymorphism

package [Link];

import [Link];
import [Link];

public class Example3 {


public static void main(final String[] args) {
Object o;

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];

public class Example3 {


public static void main(final String[] args) {
Object o;

o = new Long(1);
[Link]([Link]());
o = new Frame();
[Link]([Link]());
}
}

38/171
General Definitions

 Parametric polymorphism
public class NonGenericBox {
private Object object;

public void set(final Object object) {


[Link] = object;
}
public Object get() {
return [Link];
}
}

public void useOfNonGenericBox() {


final NonGenericBox aNonGenericBox = new NonGenericBox();
[Link](new String());
final String myString = (String) [Link]();
[Link](myString);
}

39/171
Must cast to ask
General Definitions compiler to allow
the assignment
 Parametric polymorphism
public class NonGenericBox {
private Object object;

public void set(final Object object) {


[Link] = object;
}
public Object get() {
return [Link];
}
}

public void useOfNonGenericBox() {


final NonGenericBox aNonGenericBox = new NonGenericBox();
[Link](new String());
final String myString = (String) [Link]();
[Link](myString);
}

40/171
General Definitions

 Parametric polymorphism
public class NonGenericBox {
private Object object;

public void set(final Object object) {


[Link] = object;
}
public Object get() {
return [Link];
}
}

public void useOfNonGenericBox() {


final NonGenericBox aNonGenericBox = new NonGenericBox();
[Link](new String());
final Integer myInteger = (Integer) [Link]();
[Link](myInteger);
}

41/171
Legal!
General Definitions

 Parametric polymorphism
public class NonGenericBox {
private Object object;

public void set(final Object object) {


[Link] = object;
}
public Object get() {
return [Link];
}
}

public void useOfNonGenericBox() {


final NonGenericBox aNonGenericBox = new NonGenericBox();
[Link](new String());
final Integer myInteger = (Integer) [Link]();
[Link](myInteger);
}

42/171
General Definitions

 Parametric polymorphism

We use Java vocabulary in the following 43/171


Type parameter
General Definitions

 Parametric polymorphism

We use Java vocabulary in the following 44/171


Type variable Type parameter
General Definitions

 Parametric polymorphism

We use Java vocabulary in the following 45/171


Type variable Type parameter
General Definitions
Generic type
 Parametric polymorphism declaration

We use Java vocabulary in the following 46/171


Type variable Type parameter
General Definitions
Generic type
 Parametric polymorphism declaration
Parameterised
methods

We use Java vocabulary in the following 47/171


Type variable Type parameter
General Definitions
Generic type
 Parametric polymorphism declaration
Parameterised
methods
Type argument

We use Java vocabulary in the following 48/171


General Definitions

 Parametric polymorphism
public class GenericBox<T> {
private T t;

public void set(final T t) {


this.t = t;
}
public T get() {
return this.t;
}
}

public void useOfGenericBox() {


final GenericBox<String> aGenericBox = new GenericBox<String>();
[Link](new String());
final String myString = [Link]();
[Link](myString);
}

49/171
General Definitions

 Parametric polymorphism
public class GenericBox<T> {
private T t;

public void set(final T t) {


this.t = t;
}
public T get() {
return this.t;
}
}

public void useOfGenericBox() {


final GenericBox<String> aGenericBox = new GenericBox<String>();
[Link](new String());
final Integer myInteger = (Integer) [Link]();
[Link](myInteger);
}

50/171
Illegal!
General Definitions

 Parametric polymorphism
public class GenericBox<T> {
private T t;

public void set(final T t) {


this.t = t;
}
public T get() {
return this.t;
}
}

public void useOfGenericBox() {


final GenericBox<String> aGenericBox = new GenericBox<String>();
[Link](new String());
final Integer myInteger = (Integer) [Link]();
[Link](myInteger);
}

51/171
General Definitions

 Parametric polymorphism
package [Link];

public class Example4 {


public static void main(final String[] args) {
[Link](Util.<String>compare("a", "b"));
[Link](Util.<String>compare(new String(""), new Long(1)));
[Link]([Link](new String(""), new Long(1)));
}
}

public class Util {


public static <T> boolean compare(T t1, T t2) {
return [Link](t2);
}
}

52/171
General Definitions

 Parametric polymorphism
package [Link];

public class Example4 {


public static void main(final String[] args) {
[Link](Util.<String>compare("a", "b"));
[Link](Util.<String>compare(new String(""), new Long(1)));
[Link]([Link](new String(""), new Long(1)));
}
}

public class Util {


public static <T> boolean compare(T t1, T t2) {
return [Link](t2);
}
}

Generic method 53/171


Explicit calls
General Definitions

 Parametric polymorphism
package [Link];

public class Example4 {


public static void main(final String[] args) {
[Link](Util.<String>compare("a", "b"));
[Link](Util.<String>compare(new String(""), new Long(1)));
[Link]([Link](new String(""), new Long(1)));
}
}

public class Util {


public static <T> boolean compare(T t1, T t2) {
return [Link](t2);
}
}

Generic method 54/171


Explicit calls
General Definitions

 Parametric polymorphism
package [Link];

public class Example4 {


public static void main(final String[] args) {
[Link](Util.<String>compare("a", "b"));
[Link](Util.<String>compare(new String(""), new Long(1)));
[Link]([Link](new String(""), new Long(1)));
}
}

public class Util {


Implicit call
public static <T> boolean compare(T t1, T t2) {
return [Link](t2);
}
}

Generic method 55/171


Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
56/171
Generics Definitions

“A generic type is a generic class or


interface that is parameterized over types.”

—The Java Tutorials, Oracle

57/171
Generics Definitions

 Java
generics are one implementation of
parametric polymorphism
– Type erasure

 Type parameters can be constrained


– Lower bounds
– Upper bounds
to obtain bounded type parameters
58/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
59/171
Generics Definitions

 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

 Predicative parametric polymorphism


– A type T containing a type variable  may not be
used in such a way that  is instantiated to a
polymorphic type

61/171
Generics Definitions

 Predicative parametric polymorphism


– A type T containing a type variable  may not be
used in such a way that  is instantiated to a
polymorphic type

final GenericBox<String> aGenericBox = new GenericBox<String>();


[Link](new String());

final GenericBox<List<String>> aGenericBox = new GenericBox<List<String>>();


[Link](new String());

62/171
Generics Definitions

 Predicative parametric polymorphism


– A type T containing a type variable  may not be
used in such a way that  is instantiated to a
polymorphic type

final GenericBox<String> aGenericBox = new GenericBox<String>();


[Link](new String());

final GenericBox<List<String>> aGenericBox = new GenericBox<List<String>>();


[Link](new String());

63/171
Generics Definitions

 Impredicative parametric polymorphism


– Example 1

– Example 2

64/171
Generics Definitions

 Impredicative parametric polymorphism


– Example 1
final GenericBox<List<String>> aGenericBox = new GenericBox<List<String>>();
[Link](new String());

– Example 2

65/171
Generics Definitions

 Impredicative parametric polymorphism


– Example 1
final GenericBox<List<String>> aGenericBox = new GenericBox<List<String>>();
[Link](new String());

– Example 2
import [Link];

public interface ISort<E extends Comparable<E>> {


public List<E> sort(final List<E> aList);
}

66/171
Generics Definitions

 Bounded parametric polymorphism


import [Link];

public interface ISort<E extends Comparable<E>> {


public List<E> sort(final List<E> aList);
}

The type E of the list elements must implement


the interface Comparable

67/171
Generics Definitions

 Bounded parametric polymorphism

“Bounded genericity is less about limiting the


types accepted by [a] generic class […] and
more about giving the generic class a more
complete information on its generic type T […] to
validate the call to its methods at compile time.”
—paercebal

[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
}
}

Must be comparable (with itself) 70/171


Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
71/171
Generics Definitions

 Other bounded parametric polymorphisms

Java

C++

72/171
Generics Definitions

 Other bounded parametric polymorphisms

“This feature is provided as-is and where-used


by the compiler: in a way similar to duck typing,
but resolved at compile-time. [Compilation
succeeds] only if the generic type class
[declares] the [expected method].”
—paercebal

[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();
}
};

No common type 75/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(); 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;
}

“Static” duct typing 78/171


Generics Definitions

 Duck typing
– Dynamically-typed languages: Smalltalk
– Statically-typed language: C++

“When I see a bird that walks like a duck and


swims like a duck and quacks like a duck, I call
that bird a duck.”

—Alex Martelli or James W. Riley


79/171
Generics Definitions

 Dynamically-typed languages: Smalltalk


Object subclass: #D
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.

D compile: 'needAFooMethod: anObjectWithaFooMethod


"Example of duck typing"
anObjectWithaFooMethod foo.'.

80/171
Generics Definitions

 Dynamically-typed languages: Smalltalk


Object subclass: #D
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.

D compile: 'needAFooMethod: anObjectWithaFooMethod


"Example of duck typing"
anObjectWithaFooMethod foo.'.

Any object with a


foo method will do 81/171
Generics Definitions

 Dynamically-typed languages: Smalltalk


SMUtilities subclass: #D1
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.

D1 compile: 'foo
Transcript show: ''D1'' ; cr.'.

PointArray variableWordSubclass: #D2


instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.

D2 compile: 'foo
Transcript show: ''D2'' ; cr.'.

82/171
Generics Definitions

 Dynamically-typed languages: Smalltalk


SMUtilities subclass: #D1
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.

D1 compile: 'foo
Transcript show: ''D1'' ; cr.'.

PointArray variableWordSubclass: #D2


instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.

D2 compile: 'foo
Transcript show: ''D2'' ; cr.'.
Two unrelated
classes 83/171
Generics Definitions

 Dynamically-typed languages: Smalltalk

d := D new.
d needAFooMethod: (D1 new).
d needAFooMethod: (D2 new).

D1
D2

84/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
85/171
Does not compile
When to Use Generics

 Scenario 1: you want to enforce type safety


for containers and remove the need for
typecasts when using these containers
public final class Example1 {
public static void main(final String[] args) {
final List untypedList = new ArrayList();
[Link](new String());
final Integer i = (Integer) [Link](0);

final List<String> typedList = new ArrayList<String>();


[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

86/171
When to Use Generics

 Scenario 2: you want to build generic


algorithms that work on several types of
(possible unrelated) things

import [Link];

public interface ISort<E extends Comparable<E>> {


public List<E> sort(final List<E> aList);
}

87/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
88/171
How to Use Generics

 Lots of resources
 Lots of discussions

 First step [Link]


tutorial/java/generics/[Link]
 Then, [Link]
q=%22java+generics%22
– 1,323 results as of 2013/04/14
89/171
How to Use Generics

 Typed containers, before


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List untypedList = new ArrayList();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

90/171
How to Use Generics

 Typed containers, what happens?


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List untypedList = new ArrayList();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

91/171
How to Use Generics

 Typed containers, what happens?


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List untypedList = new ArrayList();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

Exception in thread "main" [Link]:


[Link] cannot be cast to [Link]
at [Link]([Link])

92/171
How to Use Generics

 Typed containers, another look


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List untypedList = new ArrayList();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

93/171
How to Use Generics

 Typed containers, another look


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List untypedList = new ArrayList();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

List and ArrayList


are raw types, compiler
cannot typecheck 94/171
How to Use Generics

 Typed containers, solution


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List<String> typedList = new ArrayList<String>();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

95/171
How to Use Generics

 Typed containers, solution


import [Link];
import [Link];

public final class Example1Before {


public static void main(final String[] args) {
final List<String> typedList = new ArrayList<String>();
[Link](new String());
final Integer i = (Integer) [Link](0);
}
}

Does not compile because String


and Interger are not compatible 96/171
How to Use Generics

 Family of algorithms, before


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();
}
97/171
How to Use Generics

 Family of algorithms, what happens?


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();
}
98/171
Forces clients
How to Use Generics to use Object

 Family of algorithms, what happens?


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();
}
99/171
How to Use Generics

 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();
}
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

 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();
}
102/171
How to Use Generics

 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();
}
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

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
105/171
Caveats with Generics

 ints and Integers, before

public interface List extends Collection {


...
boolean add(Object o);
boolean remove(Object o);
Object remove(int index);
...
}

106/171
Caveats with Generics

 ints and Integers, now

public interface List<E> extends Collection<E> {


...
boolean add(E e);
boolean remove(Object o);
E remove(int index);
...
}

107/171
Caveats with Generics

 ints and Integers, now

public interface List<E> extends Collection<E> {


...
boolean add(E e);
boolean remove(Object o);
E remove(int index);
...
}

108/171
Caveats with Generics

 ints and Integers, what happens?


import [Link];
import [Link];

public class Autoboxing {


public static void main(String[] args) {
final List<Integer> list = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

[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];

public class Autoboxing {


public static void main(String[] args) {
final List<Integer> list = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

[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];

public class Autoboxing {


public static void main(String[] args) {
final List<Integer> list = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

[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];

public class Autoboxing {


public static void main(String[] args) {
final List<Integer> list = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

[Link](1);
[Link](new Integer(1));

}
}
[Link]([Link]());
0
112/171
Caveats with Generics

 Use of clone(), before

import [Link];

public class CloningBefore {


public static void main(final String[] args) {
final ArrayList list1 = new ArrayList();
[Link](new Integer(1));
[Link](new Integer(2));

final ArrayList list2 = (ArrayList) [Link]();


[Link](list2);
}
}

[Link]
java-how-to-use-clone-and-what-about-the-cast-check 113/171
No complains
Caveats with Genericsfor the compiler

 Use of clone(), before

import [Link];

public class CloningBefore {


public static void main(final String[] args) {
final ArrayList list1 = new ArrayList();
[Link](new Integer(1));
[Link](new Integer(2));

final ArrayList list2 = (ArrayList) [Link]();


[Link](list2);
}
}

[Link]
java-how-to-use-clone-and-what-about-the-cast-check 114/171
Caveats with Generics

 Use of clone(), now

import [Link];

public class CloningNow {


public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();


[Link](list2);
}
}

115/171
Caveats with Generics

 Use of clone(), now

import [Link];

public class CloningNow {


public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();


[Link](list2);
}
}

116/171
Type safety: Unchecked cast from
Caveats to
Object with Generics
ArrayList<Integer>
 Use of clone(), now

import [Link];

public class CloningNow {


public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();


[Link](list2);
}
}

117/171
Caveats with Generics

 Use of clone(), what happens?


– Compiler is now “stricter”
– Compiler warns of a type-unsafe operation

118/171
Caveats with Generics

 Use of clone(), solution


– Use copy-constructor
import [Link];

public class CloningSolution {


public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

final ArrayList<Integer> list2 = new ArrayList<Integer>(list1);


[Link](list2);
}
}

to obtain type-safety and remove any warning


119/171
Caveats with Generics

 Use of clone(), solution


– Use copy-constructor
import [Link];

public class CloningSolution {


public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

final ArrayList<Integer> list2 = new ArrayList<Integer>(list1);


[Link](list2);
}
}

to obtain type-safety and remove any warning


120/171
Caveats with Generics

 Use of clone(), solution


– Suppress warning
public class CloningSolutionWarning {
public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

@SuppressWarnings("unchecked")
final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();
[Link](list2);
}
}

121/171
Caveats with Generics

 Use of clone(), solution


– Suppress warning
public class CloningSolutionWarning {
public static void main(final String[] args) {
final ArrayList<Integer> list1 = new ArrayList<Integer>();
[Link](1);
[Link](new Integer(2));

@SuppressWarnings("unchecked")
final ArrayList<Integer> list2 = (ArrayList<Integer>) [Link]();
[Link](list2);
}
}

… not really a solution!


122/171
Caveats with Generics

 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]();
}
...
}

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]();
}
...
}

The method newInstance()


is undefined for the type T 125/171
Caveats with Generics

 Instantiating a type variable, what happens?


public class InstantiatingTypeParameterProblem<T> {
public static void main(final String[] args) {
...
}
public T getInstanceOfT (){
// Neither lines work:
return new T();
return [Link]();
}
...
}

The type parameter T is erased at compile-time,


the JVM cannot use it at run-time

126/171
Caveats with Generics

 Instantiating a type variable, solution #1


– Pass the class of T as parameter

public class InstantiatingTypeParameterSolution1<T> {


public static void main(final String[] args) {
...
}
public T getInstanceOfT(final Class<T> classOfT) {
return [Link]();
}
...
}

127/171
Caveats with Generics

 Instantiating a type variable, solution #2


– Pass a factory of T as parameter
interface Factory<T> {
T getInstance();
}
class Something {
public static class FactoryOfSomething implements Factory<Something> {
public Something getInstance() {
return new Something();
}
}
}
public class InstantiatingTypeParameterSolution2<T> {
public static void main(final String[] args) {
...
}
public T getInstanceOfT(final Factory<T> factory) {
return [Link]();
}
...
}
128/171
Caveats with Generics

 Instantiating a type variable, solution #3


– Prevent type erasure by specialising an
interesting class

public class InstantiatingTypeParameterSolution3 extends GenericClass<String> {


public static void main(final String[] args) {
final InstantiatingTypeParameterSolution3 i =
new InstantiatingTypeParameterSolution3();
[Link]();
}
public void foo() {
final Object s = [Link]();
[Link]([Link]());
}
}

129/171
Type argument
Caveats with Generics and subclassing

 Instantiating a type variable, solution #3


– Prevent type erasure by specialising an
interesting class

public class InstantiatingTypeParameterSolution3 extends GenericClass<String> {


public static void main(final String[] args) {
final InstantiatingTypeParameterSolution3 i =
new InstantiatingTypeParameterSolution3();
[Link]();
}
public void foo() {
final Object s = [Link]();
[Link]([Link]());
}
}

130/171
Caveats with Generics

 Instantiating a type variable, solution #3


– Prevent type erasure by specialising an
interesting class
import [Link];

abstract class GenericClass<T> {


public T getInstanceOfT() {
final ParameterizedType pt =
(ParameterizedType) [Link]().getGenericSuperclass();
final String parameterClassName =
[Link]()[0].toString().split("\\s")[1];
T parameter = (T) [Link](parameterClassName).newInstance();
return parameter;
}
}

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];

abstract class GenericClass<T> {


public T getInstanceOfT() {
final ParameterizedType pt =
(ParameterizedType) [Link]().getGenericSuperclass();
final String parameterClassName =
[Link]()[0].toString().split("\\s")[1];
T parameter = (T) [Link](parameterClassName).newInstance();
return parameter;
}
}

132/171
Caveats with Generics

 Implicit generic methods


– As with explicit generic methods, use Object in
the generated bytecodes
public final class Example4 {
public static void main(final String[] args) {
[Link](Util4.<String> compare("a", "b"));
// The following line, as expected, produces a type mismatch error
// [Link](Util.<String> compare(new String(""), new Long(1)));
[Link]([Link](new String(""), new Long(1)));
}
}
final class Util4 {
public static <T> boolean compare(final T t1, final T t2) {
return [Link](t2);
}
}

133/171
Caveats with Generics

 Implicit generic methods


– As with explicit generic methods, use Object in
the generated bytecodes
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 7, Locals: 1
public static void main([Link][] args);

14 invokevirtual [Link]([Link], [Link]) : boolean [29]

47 invokevirtual [Link]([Link], [Link]) : boolean [29]

to ensure backward-compatibility with


non-generic Java code
134/171
Caveats with Generics

 Multiple bounds

“A type variable with multiple bounds is a


subtype of all the types listed in the bound.
If one of the bounds is a class, it must be
specified first.”

—The Java Tutorials, Oracle


135/171
Caveats with Generics

 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

 Upper- and lower-bounded wildcards


– Type parameters can be constrained to be
• Any subtype of a type, extends
• Any supertype of a type, super
– Useful with collections of items

import [Link];

public interface ISort<E extends Comparable<E>> {


public List<E> sort(final List<E> aList);
}

138/171
Caveats with Generics

 PECS
– Collections that produce extends
– Collections that consume super

Always from the point of view of the collection

[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)

Collection<? extends Something>

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)

Collection<? super Something>

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

 Ambiguity between parameterised types


public class Example9 {
public static String f(List<String> list) {
[Link]("strings");
return null;
}
public static Integer f(List<Integer> list) {
[Link]("numbers");
return null;
}
public static void main(String[] args) {
f([Link]("asdf"));
f([Link](123));
}
}

[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

 Ambiguity between parameterised types


public class Example9 {
public static String f(List<String> list) {
[Link]("strings");
return null;
}
public static Integer f(List<Integer> list) {
[Link]("numbers");
return null;
}
public static void main(String[] args) {
f([Link]("asdf"));
f([Link](123));
}
}

[Link] 145/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
146/171
Reflecting on Generics

 Java generics use type erasure


– (Most) Type parameters / arguments are erased
at compile-time and exist at run-time only as
annotations

– Ensure backward-compatibility with pre-generic


Java code
– Limit access to type parameters / arguments
using reflection
147/171
Caveats with Generics

 Type-safe use of getClass()

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);

final Example11A anA2 = new Example11A();


final Class<? extends Example11A> anA2Class = [Link]();
[Link](anA2Class);
}
}

[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);

final Example11A anA2 = new Example11A();


final Class<? extends Example11A> anA2Class = [Link]();
[Link](anA2Class);
}
}

[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);

final Example11A anA2 = new Example11A();


final Class<? extends Example11A> anA2Class = [Link]();
[Link](anA2Class);
}
}

[Link]
No warning
is-there-a-clean-way-to-assign-the-class-of-a-generic-type-to-a-variable 150/171
Caveats with Generics

 Type-safe use of getClass()

class MyList extends ArrayList<Integer> {


}
public class Example11 {
public static void main(final String[] args) {
final List<Integer> list1 = new ArrayList<Integer>();
final Class<List<Integer>> list1Class =
(Class<List<Integer>>) [Link]();
[Link](list1Class);

final MyList list2 = new MyList();


Class<? extends List<? extends Integer>> list2Class = [Link]();
[Link](list2Class);
}
}

[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()

class MyList extends ArrayList<Integer> {


}
public class Example11 {
public static void main(final String[] args) {
final List<Integer> list1 = new ArrayList<Integer>();
final Class<List<Integer>> list1Class =
(Class<List<Integer>>) [Link]();
[Link](list1Class);

final MyList list2 = new MyList();


Class<? extends List<? extends Integer>> list2Class = [Link]();
[Link](list2Class);
}
}

[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()

class MyList extends ArrayList<Integer> {


}
public class Example11 {
public static void main(final String[] args) {
final List<Integer> list1 = new ArrayList<Integer>();
final Class<List<Integer>> list1Class =
(Class<List<Integer>>) [Link]();
[Link](list1Class);

final MyList list2 = new MyList();


Class<? extends List<? extends Integer>> list2Class = [Link]();
[Link](list2Class);
}
}

[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);

final Class<?> clazz2 = [Link](


"[Link].Example9A");
final Example10A anA2 = (Example10A) [Link]();
[Link](anA2);
}
}

[Link] 154/171
Caveats with Generics

 Obtaining the type of a type parameter


– Due to type erasure
• Type parameters are kept as annotations
• Type arguments disappear
Except for anonymous/local classes!

[Link]
get-type-of-a-generic-parameter-in-java-with-reflection 155/171
Caveats with Generics

 Obtaining the type of a type parameter

public final class Voodoo0 extends TestCase {


public static void chill(final List<?> aListWithSomeType) {
[Link](
aListWithSomeType,
[Link]);
}
public static void main(String... args) {
[Link](new ArrayList<SpiderManVoodoo0>());
}
public void test() {
[Link](new String[0]);
}
}
class SpiderManVoodoo0 {
}

156/171
Caveats with Generics

 Obtaining the type of a type parameter

public final class Voodoo0 extends TestCase {


public static void chill(final List<?> aListWithSomeType) {
[Link](
aListWithSomeType,
[Link]);
}
public static void main(String... args) {
[Link](new ArrayList<SpiderManVoodoo0>());
}
public void test() {
[Link](new String[0]);
}
}
class SpiderManVoodoo0 {
}

157/171
Caveats with Generics

 Obtaining the type of a type parameter

public static void main([Link]...);


flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=2, locals=1, args_size=1
0: new #32 // class java/util/ArrayList
3: dup
4: invokespecial #34 // Method java/util/ArrayList."<init>":()V
7: invokestatic #35 // Method chill:(Ljava/util/List;)V
10: return
LineNumberTable:
line 38: 0
line 39: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;

158/171
Caveats with Generics

 Obtaining the type of a type parameter

public final class Voodoo1 extends TestCase {


public static void chill(final List<?> aListWithSomeType) {
[Link](
aListWithSomeType,
[Link]);
}
public static void main(String... args) {
[Link](new ArrayList<SpiderManVoodoo1>() {});
}
public void test() {
[Link](new String[0]);
}
}
class SpiderManVoodoo1 {
}

159/171
Caveats with Generics

 Obtaining the type of a type parameter

public final class Voodoo1 extends TestCase {


public static void chill(final List<?> aListWithSomeType) {
[Link](
aListWithSomeType,
[Link]);
}
public static void main(String... args) {
[Link](new ArrayList<SpiderManVoodoo1>() {});
}
public void test() {
[Link](new String[0]);
}
}
class SpiderManVoodoo1 {
}

160/171
Caveats with Generics

 Obtaining the type of a type parameter

public final class Voodoo1 extends TestCase {


public static void chill(final List<?> aListWithSomeType) {
[Link](
aListWithSomeType,
[Link]);
}
public static void main(String... args) {
[Link](new ArrayList<SpiderManVoodoo1>() {});
}
public void test() {
[Link](new String[0]);
}
}
class SpiderManVoodoo1 {
}

161/171
Anonymous/local class
Caveats with Generics
stores types information
 Obtaining the type of a type parameter

public final class Voodoo1 extends TestCase {


public static void chill(final List<?> aListWithSomeType) {
[Link](
aListWithSomeType,
[Link]);
}
public static void main(String... args) {
[Link](new ArrayList<SpiderManVoodoo1>() {});
}
public void test() {
[Link](new String[0]);
}
}
class SpiderManVoodoo1 {
}

162/171
Caveats with Generics

 Obtaining the type of a type parameter

public static void main([Link]...);


flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=2, locals=1, args_size=1
0: new #32 // class net/ptidej/generics/java/erasure/Voodoo1$1
3: dup
4: invokespecial #34 // Method net/ptidej/generics/java/erasure/Voodoo1$1."<init>":()V
7: invokestatic #35 // Method chill:(Ljava/util/List;)V
10: return
LineNumberTable:
line 38: 0
line 41: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;

163/171
Caveats with Generics

 Obtaining the type of a type parameter

public static void main([Link]...);


flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=2, locals=1, args_size=1
0: new #32 // class net/ptidej/generics/java/erasure/Voodoo1$1
3: dup
4: invokespecial #34 // Method net/ptidej/generics/java/erasure/Voodoo1$1."<init>":()V
7: invokestatic #35 // Method chill:(Ljava/util/List;)V
10: return
LineNumberTable:
line 38: 0
line 41: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;

164/171
Caveats with Generics

 Obtaining the type of a type parameter

// Compiled from [Link] (version 1.7 : 51.0, super bit)


// Signature: Ljava/util/ArrayList<Lca/polymtl/ptidej/generics/java/erasure/SpiderManVoodoo1;>;
class [Link].Voodoo1$1 extends [Link] {

...

// Method descriptor #11 ()V


// Stack: 1, Locals: 1
Voodoo1$1();
0 aload_0 [this]
1 invokespecial [Link]() [13]
4 return
Line numbers:
[pc: 0, line: 38]
[pc: 4, line: 1]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: new ....[Link].Voodoo1(){}

...
}
165/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
166/171
Conclusion

 Java generics

“Implement generic algorithms that work on


a collection of different types”

—The Java Tutorials, Oracle

167/171
Conclusion

 Scenario 1: you want to enforce type safety


for containers and remove the need for
typecasts when using these containers
 Scenario 2: you want to build generic
algorithms that work on several types of
(possible unrelated) things

168/171
Conclusion

 Easyto use in simple cases


 Some caveats, though

 Can be very tricky is corner cases


– Use them sparingly and purposefully

169/171
Outline

 History  When to Use Generics


 Problem  How to Use Generics
 Special Case  Caveats with Generics
 General Definitions  Reflecting on Generics
 Generics Definitions  Conclusion
– Parametric  Few References
Polymorphism
– Other Bounded
Parametric
Polymorphisms
170/171
Outline
 In no particular order
– [Link]
– [Link]
Sections/[Link]#FAQ502
– [Link]
lysark/[Link]
– [Link]
– [Link]
to_retrieve_generic_parameters#Anonymous_classes
– [Link] generics/
– [Link]

171/171

You might also like