一般情况下,泛型最通常应用于集合,如set和Map,以及单元素的容器,如ThreadLocal等。在这些语法中一般情况下,这些容器都被充当被参数化了的容器,意味着每个容器只能有一个或者多个固定数目的类型参数。如一个Set只有一个类型参数,用于表示元素类型。一个Map有两个类型参数,表示它的键和值类型。(个人认为类型参数就是指定了类型的参数。这也是泛型的意义所在)
但是有时候我们可能需要更多的灵活性,比如数据库行可以有任意多的列,每个列的类型可能不一样,如果能以类型安全的方式访问所有列就好了。目前,有一种方法可以实现,就是将键值(key)进行参数化而不是对整个容器进行参数化。然后将参数化的键值提交给容器,来插入或者获取值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public
class
Favorite {
/**
* 注意这个地方Map的key进行了参数化,而非是Map本身
*/
private
Map<Class<?>,Object> map =
new
HashMap<Class<?>, Object>();
private
Map<List<?>,Object> map2 =
new
HashMap<List<?>, Object>();
public
<E>
void
add(Class<E> type,E instance) {
if
(type!=
null
) {
map.put(type, instance);
}
}
public
<E>
void
add(List<E> type,E instance) {
if
(type!=
null
) {
map2.put(type, instance);
}
}
public
<E> E
get
(Class<E> type) {
Object
object
= map.
get
(type);
return
type.cast(
object
);
}
public
static
void
main(String[] args) {
Favorite f =
new
Favorite();
f.add(String.
class
,
"string"
);
//可以插入String类型
f.add(Integer.
class
, Integer.valueOf(123));
//可以插入int类型
f.add(
new
ArrayList<String>(),
"String"
);
//可以插入String类型
f.add(
new
ArrayList<Integer>(), 123);
//可以插入int类型
String s1 = f.
get
(String.
class
);
Integer i = f.
get
(Integer.
class
);
System.
out
.println(s1);
System.
out
.println(i);
}
}
|
上面的例子就是实现了一个可以指定多个类型的插入和读取,且是类型安全的。
这个例子需要注意的是
private Map<Class<?>,Object> map = new HashMap<Class<?>, Object>();
每个Favorite实例都得到一个被称作map的私有
Map<Class<?>,Object>
的支持。开始的时候,我们可能会将不能将任何东西放入到这个Map中去,因为其实无限制通配符,但是其实事实正好相反,我们可以删除任意类型的数据,原因是因为这个通配符是嵌套的,它不是属于通配符类型的Map的类型,而是他的key的类型。由此可见,每个键都可以有一个不同的参数化类型,本示例中Class<String> Class<Integer>。