虽然一直以来,Java都提供了强制类型转换,但是那确实是Java的弱点,因为你是在取数据的时候才保证了类型安全(Type-safe),而不是在存储数据的时候就做好这项工作,Java5提供了Generic来保证这项工作,从而提高了Java的类型安全(Type-safe)。

 

使用Type-Safe的List

只接受String类型的List申明代码如下:

1 List<String> list=new LinkedList<String>();
2 list.add("hello");

list只能接受String类型,如果你试图传入其他的类型那么,会产生编译错误。当然其中的String可以换成其他的类型如Integer,Boolean或者自己申明的类类型(class type),但不可以是元类型(primitive type)。也许你会担心int与Integer之间的转换,但是当你见识到autoboxing之后,你就会释怀。

其他的collection class也如list一样使用Generic来保证Type-Safe

 

使用Type-Safe的Map

list接受了一个Generic变量,而Map则需要接受两个,代码如下:

1 Map<String,String> map=new HashMap<String,String>();
2 map.put("key", "value");

其中的String与上面list之中的一样。

 

Interating Over Parameterized Type 迭代器中的参数类型(泛型)

 1 List<String> list=new LinkedList<String>();
2 list.add("hello");
3 list.add("word");
4
5 for(Iterator i=list.iterator();i.hasNext();){
6 String s=(String) i.next();//这里必须进行强制类型转换,因为Iterator中是Object类型的对象
7 }
8
9 for(Iterator<String> i=list.iterator();i.hasNext();){
10 String s= i.next();//这里不用进行强制转换,因为Iterator中在输入的时候已经成为了String对象
11 }

对比上面的5和9行会发现为什么6和10行不一样。

 

来看下面一段代码,看看你发现了什么?

1 public List<String> testGenericMethod(List<String> list){
2 list.add("hello");
3 list.add("word");
4 Map<String,List<String>> map=new HashMap<String,List<String>>();
5 map.put("helloword", list);
6 return list;
7 }

事实上,Generic的Parameterized Type(参数化类型)可以作为参数:行1,作为返回类型:行1,作为类型参数:行4.

你可能也知道Lint(棉絮)警告,虽然作为程序员,我们是一贯的不管警告,但是规避警告总是好的。所以你可以这样写代码,来减少警告:

1 List<Object> list=new LinkedList<Object>();

 

Generic与类型转换

在做类型转换的时候,通常只转换基础类型,而不转换Generic类型,如下所示:

1 LinkedList<Float> list=new LinkedList<Float>();
2 List<Float> list2=list;//这个是允许的
3 LinkedList<Number> list3=list;//这个存在编译错误,具体的不再详细解释

 

类型通配符

有时候我们不知道某个代码提供给别人后,他们会怎么样使用,所以需要一个通配符,如下所示

1 public void testGenericMethod(List<?> list){
2 for(Iterator<?> i=list.iterator();i.hasNext();)
3 System.out.println(i.next().toString());
4 }

如果去掉其中的<?>通配符,则往往会产生unchecked警告
 

写一个Generic

好了,我想我们可以写一个Generic了,不用太复杂。

 1 class A<E>{
2 private List<E> list;
3 public A(){
4 list=new ArrayList<E>();
5 }
6 public E add(E ele){
7 list.add(ele);
8 return ele;
9 }
10 }

其中的E是用来代表一个类型参数

 

限制类型参数

有时候可能你并不想所有的类型作为类型参数,那怎么办呢?看下面一段代码:

 1 class A<E extends Number>{
2 private List<E> list;
3 public A(){
4 list=new ArrayList<E>();
5 }
6 public E add(E ele){
7 list.add(ele);
8 return ele;
9 }
10 }

与原来的相比较在E后面多出了 extends 语句,这样传进来的类型就必须是Number或者其子类型了。

posted on 2011-10-25 10:11  Yakov  阅读(564)  评论(0编辑  收藏  举报