Part 07 - Generic Programming
Part 07 - Generic Programming
Outline
■ Generic class
■ Generic method
■ Subtype & wildcard
■ Retrictions & limitations
■ Generic class & Inheritance
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 2/48
What is Generic Programming?
■ Generic programming means to write code that can be
reused for objects of many different types
❑ List of DictionaryEntries / pets
❑ Sorting Integers / Dictionary entries
■ Before JDK 5.0, generic programming in Java was
always achieved with inheritance.
❑ What we have been doing:
public class MyList {// items could be objects of any classes
public void add(Object o) {…}
public Object getFirst() {…}
...
}
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 3/48
Defining the idea Behind Java Generics
◼ Generic Types:
◼ “generic class or interface
◼ which is parameterized over
types”
◼ Generic Methods:
◼ “Method featuring type
parameters”
◼ https://docs.oracle.com/javase/tutorial/java/generics/types.html
◼ http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#What is a parameterized (or
generic) type?
◼ http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedMethods.html#What is a parameterized (or generic)
method?
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 4/48
Why Bother?
List<String> list
= new ArrayList<String>();
list.add("hello");
String s = list.get(0);
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 5/48
Why Bother?
?
List list = new ArrayList();
What happens if
list.add("hello");
!
list.add(new Integer(42));
Runtime Exception
String s = (String) list.get(0);
Integer s = (Integer) list.get(1);
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 6/48
Why Bother?
Encourages programmers to
write generic classes
e.g.
• Originally meant to support Java Collections
▪ A List of <Integer> has the same underlying logic as a List of
<Double>
• Usable now by anyone to produce better code
▪ Define the concept of List of <something>
1
1
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 7/48
Is it possible to
do Generic
Programming
w/o Generics?
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 8/48
Consider this…
public class Box {
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 9/48
Let’s try it out!
b.set(n1);
Double n2 = b.get();
}
? How do we fix
this?
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 10/48
Now, Let’s fix it!
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 11/48
New Plan!
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 12/48
Introducing… Generic Types! See the difference?
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 13/48
Anatomy of a Generic Type
Formal Type
Class / Interface Parameters
Section <…>
public class Box<T> {
Formal Type private T t;
Parameters
Type Variables
public void set(T t)
non-primitive type,
{ this.t = t; }
array type,
other type variable
public T get()
Used wherever a { return t; }
data type would be
}
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 14/48
Naming Conventions for Formal Type Parameters
◼ V - Value
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 15/48
How to Instantiate a Generic Class
Parameterized Type;
i.e. instantiation of a
generic type
Box<Integer> integerBox = new Box<Integer>();
Actual Type
Box<Integer> integerBox = new Box<>(); Type Argument
Argument
Since Java 7+
“Type Inference”
? What is Type
Inference?
21
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 16/48
What happens if we do not use <> at all?
Raw types!
public class Box<T> {
public void set(T t) { /* ... */ } Legacy code < JDK 5.0
// ...
}
When using raw types, you
essentially get pre-generics
Box rawBox = new Box(); behavior — a Box gives you
Objects
?
// ...
} What is Type
Erasure?
Box rawBox = new Box<Integer>(); 22
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 17/48
Two problems with using inheritance
◼ 1. A cast is necessary whenever you retrieve a value:
//items could be objects of any classes
public class MyList {
public void add(Object o) {…}
public Object getFirst() {…}
}
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 18/48
Two problems with using inheritance
▪ 2. There is no error checking. You can add objects of any class.
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 19/48
Using generic classes
■ Many Java library classes have been made generic, they
can be used in a way that indicates the type of object they
hold.
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 20/48
Generic Class
■ A generic class is a class with one or more type parameters
that indicate the element type
Type parameter T,
public c l a s s Pair<T>
enclosed in angle brackets < >
{
private T f i r s t ;
private T second;
public Pa i r ( ) { f i r s t = n u l l ; second = n u l l ; }
public Pair(T f i r s t , T second)
{ t h i s . f i r s t = f i r s t ; this.second = second; }
public T g e t F i r s t ( ) { return f i r s t ; }
public T getSecond() { return second; }
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 21/48
Example
public c l a s s Pair<T>
{
private T f i r s t ;
private T second;
public Pa i r ( ) { f i r s t = n u l l ; second = n u l l ; }
public Pair(T f i r s t , T second)
{ t h i s . f i r s t = f i r s t ; this.second = second; }
public T g e t F i r s t ( ) { return f i r s t ; }
public T getSecond() { return second; }
}
...
Pair<String> mm = new Pair<String> ( " 1 s t " , " 2 n d " ) ;
System.out.println(mm.getFirst() + " , " + mm.getSecond());
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 22/48
More than one type parameters
public T g e t F i r s t ( ) { return f i r s t ; }
public U getSecond() { return second; }
}
...
Pa i r < S t r i n g , Integer> mm = new Pa i r < S t r i n g , Integer> ( " 1 s t " , 1 ) ;
System.out.println(mm.getFirst() + " , " + mm.getSecond());
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 23/48
Generic method
■ A generic method is one with type parameters
❑ inside an ordinary class or generic class
cla s s ArrayAlg {
public s t a t i c <T> T getMiddle(T[] a){
return a[a.length / 2 ] ; }
}
■ Usage:
❑ Concrete type is specified in the method call
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 24/48
Bounds for Type parameters
c l a s s ArrayAlg {
public s t a t i c <T> T min(T[] a ) // almost correct
{
i f (a == n u l l || a.length == 0 ) return n u l l ;
T smallest = a [ 0 ] ;
f o r ( i n t i = 1 ; i < a.length; i + + )
i f (smallest.compareTo(a[i]) > 0)
smallest = a [ i ] ;
return smallest; What if T does not provide compareTo()
} method?
}
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 25/48
Bounds for Type Parameters
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 26/48
Bounds for Type Parameters
c l a s s ArrayAlg{
/**
Gets the minimum and maximum of an array of objects of type T.
@param a an array of objects of type T
@return a p a i r with the min and max value, or
n u l l i f a i s n u l l or empty
*/
public s t a t i c <T extends Comparable> Pair<T> minmax(T[] a){
i f (a == n u l l || a.length == 0) return n u l l ;
T min = a [ 0 ] ;
T max = a [ 0 ] ;
f o r ( i n t i = 1; i < a.length; i + + )
{
i f (min.compareTo(a[i]) > 0) min = a [ i ] ;
i f (max.compareTo(a[i]) < 0) max = a [ i ] ;
}
return new Pair<T>(min, max);
}
} ...
String[] words = { "Mary", "had", "a", "little", "lamb" };
Pair<String> mm = ArrayAlg.minmax(words);
System.out.println("min = " + mm.getFirst());
System.out.println("max = " + mm.getSecond());
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 27/48
Restrictions and Limitations
■ Before JDK 5.0, primitive types cannot be substituted for a type
parameter
❑ Pair<int> or Pair<double>… unaccepted (compile error)
■ Pair<Integer> or Pair<Double>
■ From JDK 5.0 on, wrappers are automatically used.
■ Runtime type inquiry
❑ instanceof and getClass() ignore type parameter
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 28/48
Inheritance and Generic Types
■ No relationship!
Animal Pair<Animal>
No relationship
Cat Pair<Cat>
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 29/48
Wildcards
■ To specify a Pair capable of holding some subtype of
Animal:
❑ Pair<? extends Animal> aPair = ...;
...
Pair<Cat> catBuddies = new Pair<Cat>(tomCat, timCat);
Pair<? extends Animal> wildcardBuddies = catBuddies; // OK
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 30/48
Exercise
■ Write a generic method that sorts an array in ascending order
c l a s s ArrayAlg {
public s t a t i c . . . s o r t ( T [ ] a){ //sort a
}
public static <T extends Comparable<T>> void sort (T[] a) {
int n = a.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (a[j].compareTo(a[j + 1]) > 0) {
// Swap if greater
T temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp;
}
}
}
}
■ Example of client code
...
S t r i n g [ ] names = { " Joh n " , " Pe t e r " , " Joe " } ;
ArrayAlg.<String>sort(names); // ( " J o e " , "John", " Pe t e r " )
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 31/48
Exercise
c l a s s ArrayAlg {
public s t a t i c <T extends Comparable> void s o r t ( T [ ] a)
Write {
a generic method that sorts an array in
ascending f o r ( i norder
t i = 0 ; i < a .le n gth () - 1 ; i + + )
f o r ( i n t j = i + 1 ; j < a . l e n g t h ( ) ; j++)
i f (a[i].compareTo(a[j]) > 0 ) {
T temp = a [ i ] ;
a [ i ] = a [ j ] ; a [ j ] = temp;
}
}
}
...
S t r i n g [ ] names = { " Joh n " , " Pe t e r " , " Joe " } ;
ArrayAlg.<String>sort(names); // ( " J o e " , "John", " Pe t e r " )
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 32/48
BÀI TẬP
◼ Viết phương thức Generic tìm phần tử lớn nhất trong
mảng
◼ Yêu cầu:
• Viết một phương thức generic để tìm phần tử lớn nhất
trong một mảng.
• Không sử dụng phương thức Collections.max() hoặc
Arrays.sort().
◼ Gợi ý:
• Dùng <T extends Comparable<T>> để đảm bảo kiểu dữ
liệu có thể so sánh được
Khoa
KhoaCNTT
CNTT –– Trường
ĐH NôngĐH Nông
Lâm Lâm01/2016
TP. HCM TP. HCM 33/48