Generics
Hsuan-Tien Lin
Department of CSIE, NTU
OOP Class, May 31-June 1, 2010
Motivation of Generics
1 c l a s s ANYArray {
2 p r i v a t e ANY [ ] myarr ;
3 p u b l i c ANYArray (i n t l e n ) { myarr = new ANY [ l e n ] ; }
4 p r o t e c t e d ANY g e t (i n t n ) { r e t u r n myarr [ n ] ; }
5 p r o t e c t e d v o i d s e t (i n t n , ANY o ) { myarr [ n ] = o ; }
6 p u b l i c v o i d s h o w A l l ( ) {
7 f o r(i n t i = 0 ; i <myarr . l e n g t h ; i ++)
8 System . o u t . p r i n t l n ( myarr [ i ] ) ;
9 }
10 }
Yes, by identifying the common parts, and then replacing manual way: sed ’s/ANY/String/’ ANYArray.java >
StringArray.java
C++ Solution (roughly)
1 t e m p l a t e <c l a s s ANY>
2 c l a s s A r r a y {
3 p r i v a t e ANY [ ] myarr ;
4 p u b l i c A r r a y (i n t l e n ) { myarr = new ANY [ l e n ] ; }
5 p r o t e c t e d ANY g e t (i n t n ) { r e t u r n myarr [ n ] ; }
6 p r o t e c t e d v o i d s e t (i n t n , ANY o ) { myarr [ n ] = o ; }
7 p u b l i c v o i d s h o w A l l ( ) {
8 f o r(i n t i = 0 ; i <myarr . l e n g t h ; i ++)
9 System . o u t . p r i n t l n ( myarr [ i ] ) ;
10 }
11 }
12
13 {
14 Array < S t r i n g > s a r r ( 5 ) ;
15 s a r r . s e t ( 3 , " l a l a l a " ) ;
16 }
basically, the step sed ’s/ANY/String/’ ANYArray.cpp >
StringArray.cpp done by compiler
code automatically duplicates during complication as you use
Array<String>, Array<Integer>, Array<Double>, ...
Java Solution (roughly)
1 c l a s s Array <ANY> {
2 p r i v a t e ANY [ ] myarr ;
3 p u b l i c A r r a y (i n t l e n ) { myarr = (ANY [ ] ) (new O b j e c t [ l e n ] ) ; }
4 p r o t e c t e d ANY g e t (i n t n ) { r e t u r n myarr [ n ] ; }
5 p r o t e c t e d v o i d s e t (i n t n , ANY o ) { myarr [ n ] = o ; }
6 p u b l i c v o i d s h o w A l l ( ) {
7 f o r(i n t i = 0 ; i <myarr . l e n g t h ; i ++)
8 System . o u t . p r i n t l n ( myarr [ i ] ) ;
9 }
10 }
11
12 {
13 Array < S t r i n g > s a r r ( 5 ) ;
14 s a r r . s e t ( 3 , " l a l a l a " ) ;
15 }
the ANY → Object step is automatically done by compiler: a true
one-class solution
How does duplicating solution compare
with one-class solution?
How can we write one class for arbitrary
sets of arbitrary size while keeping type
information?
Should StringSet extend ObjectSet?
3FNIGX%VVE] EVV ! RI[ 7XVMRK%VVE]
EVV EHH RI[ -RXIKIV
Java Solution: Generics (since 1.4)
no manual duplicating (as opposed to old languages): save coding efforts
no automatic duplicating (as opposed to C++): save code size and re-compiling efforts
check type information very strictly by compiler (as opposed to single-object polymorphism): ensure type safety in JVM
Note: type information erased after compilation
Type Erasure: Mystery 1
1 c l a s s Set <T> {
2 Set ( ) {
3 T [ ] a r r = new T [ 1 0 ] ;
4 a r r [ 0 ] = new T ( ) ;
5 }
6 }
cannot new with an “undetermined type” T (no T in runtime)
Type Erasure: Mystery 2
1 c l a s s Set <T> {
2 }
3 p u b l i c c l a s s Fun {
4 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] argv ) {
5 Set < S t r i n g > [ ] a r r = new Set < S t r i n g > [ 2 0 ] ;
6 a r r [ 0 ] . addElement (new I n t e g e r ( 3 ) ) ;
7 }
8 }
cannot create generic array (after type erasure, no type
guarantee)
Use of Generics: Java Collection Framework
interfaces: Collection (Set, List) and Map
abstract classes: AbstractCollection (AbstractSet, AbstractList) and AbstractMap
concrete classes: HashSet, ArrayList, HashMap
SimpleArray I
1 c l a s s SimpleArray <E> {
2 E [ ] a r r ; i n t co unt ;
3
4 v o i d i n i t 1 (i n t i n i t _ s i z e ) {
5 a r r = new E [ i n i t _ s i z e ] ;
6 }
7 v o i d i n i t 2 (i n t i n i t _ s i z e ) {
8 a r r = new O b j e c t [ i n i t _ s i z e ] ;
9 }
10 v o i d i n i t 3 (i n t i n i t _ s i z e ) {
11 a r r = ( E [ ] ) (new O b j e c t [ i n i t _ s i z e ] ) ;
12 }
13 @SuppressWarnings ( " unchecked " )
14 v o i d i n i t 4 (i n t i n i t _ s i z e ) {
15 a r r = ( E [ ] ) (new O b j e c t [ i n i t _ s i z e ] ) ;
16 }
17 O b j e c t [ ] a r r O b j ;
18 v o i d i n i t 5 (i n t i n i t _ s i z e ) {
19 a r r O b j = new O b j e c t [ i n i t _ s i z e ] ;
20 }
21
SimpleArray II
22
23 v o i d add1 ( E element ) {
24 a r r [ co unt ++] = element ;
25 }
26
27 v o i d add2 ( E element ) {
28 a r r O b j [ co unt ++] = element ;
29 }
30 31 32 33 34 35 36 37 38 39 40 41 42 43
SimpleArray III
44 E pop1 ( ) {
45 r e t u r n a r r [ count −−];
46 }
47
48 E pop2 ( ) {
49 r e t u r n a r r O b j [ count −−];
50 r e t u r n n u l l;
51 }
52
53 E pop3 ( ) {
54 r e t u r n ( E ) a r r O b j [ count −−];
55 }
56
57 @SuppressWarnings ( " unchecked " )
58 E pop4 ( ) {
59 r e t u r n ( E ) a r r O b j [ count −−];
60 }
61 62 63 64 65
SimpleArray IV
66 boolean equals1 ( SimpleArray <E> a n o t h e r ) {
67 i f ( a n o t h e r . co unt ! = co unt ) r e t u r n f a l s e;
68 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
69 i f ( a r r [ i ] ! = a n o t h e r . a r r [ i ] )
70 r e t u r n f a l s e;
71 r e t u r n t r u e;
72 }
73 boolean equals2 ( SimpleArray <?> a n o t h e r ) {
74 i f ( a n o t h e r . co unt ! = co unt ) r e t u r n f a l s e;
75 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
76 i f ( a r r [ i ] ! = a n o t h e r . a r r [ i ] )
77 r e t u r n f a l s e;
78 r e t u r n t r u e;
79 }
80 81 82 83 84 85 86 87
SimpleArray V
88 v o i d j o i n 1 ( SimpleArray <E> a n o t h e r ) {
89 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
90 a r r [ co unt ++] = a n o t h e r . a r r [ i ] ;
91 }
92 v o i d j o i n 2 ( SimpleArray <? extends E> a n o t h e r ) {
93 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
94 a r r [ co unt ++] = a n o t h e r . a r r [ i ] ;
95 }
96 v o i d j o i n 3 ( SimpleArray <?> a n o t h e r ) {
97 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
98 a r r [ co unt ++] = a n o t h e r . a r r [ i ] ;
99 }
100 101 102 103 104 105 106 107 108 109
SimpleArray VI
110 E [ ] t o A r r a y 1 ( ) {
111 r e t u r n a r r ;
112 }
113
114 @SuppressWarnings ( " unchecked " )
115 E [ ] t o A r r a y 2 ( ) {
116 r e t u r n ( E [ ] ) a r r O b j ;
117 }
118
119 O b j e c t [ ] t o O b j e c t A r r a y 1 ( ) {
120 r e t u r n a r r ;
121 }
122 O b j e c t [ ] t o O b j e c t A r r a y 2 ( ) {
123 r e t u r n a r r ;
124 }
125
126 @SuppressWarnings ( " unchecked " )
127 <T> T [ ] t o T A r r a y 1 ( T [ ] t y p e ) {
128 r e t u r n ( T [ ] ) a r r ;
129 }
130 131
SimpleArray VII
132 v o i d j o i n 2 ( SimpleArray <? extends E> a n o t h e r ) {
133 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
134 a r r [ co unt ++] = a n o t h e r . a r r [ i ] ;
135 }
136
137 <T extends E> v o i d j o i n 2 w i t h T ( SimpleArray <T> a n o t h e r ) {
138 f o r(i n t i = 0 ; i < a n o t h e r . c oun t ; i ++)
139 a r r [ co unt ++] = a n o t h e r . a r r [ i ] ;
140 }
141 142 }
More on Type Erasure
1 A r r a y L i s t < S t r i n g > l 1 = new A r r a y L i s t < S t r i n g > ( ) ;
2 A r r a y L i s t < I n t e g e r > l 2 = new A r r a y L i s t < I n t e g e r > ( ) ;
3 System . o u t . p r i n t l n ( l 1 . g e t C l a s s ( ) == l 2 . g e t C l a s s ( ) ) ;
4 System . o u t . p r i n t l n ( l 1 i n s t a n c e o f C o l l e c t i o n < S t r i n g > ) ;