划词......
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

泛型方法及动态参数

Posted on 2007-06-17 16:19  王君  阅读(2602)  评论(0编辑  收藏  举报
参考书籍
<java generics and collection>>
oreilly 2006


本文主要讲述以下几个方面:
(1)    如何创建泛型方法;
(2) vararg(动态参数)的应用;
(3) 调用泛型方法时显式给定类型参数;


(1) 如何创建泛型方法
我们用例子来说明一下如何创建一个泛型方法:
class Lists {
public static <T> List<T> toList(T[] arr) {
        List<T> lists = new ArrayList<T>();
        for(T element : arr) {
            lists.add(element);
}
return lists;
}
}
我们可以这样进行调用
List<Integer> ints = Lists.toList(new Integer[]{1, 2, 3});
List<String> words = Lists.toList(new String[]{“a”, “b”, “c”});

上面例子的方法签名的第一个<T>,初看起来比较奇怪,和我们传统的方法签名并不相同,这个<T>表示为我们的方法声明一个类型变量(type variable),该类型变量被应用于方法签名及方法体,这个类型变量的作用域仅限于该方法本身。


(2) vararg(动态参数)的应用
将参数打包成一个数组传入方法中是一件让人讨厌的事,在jdk1.5中加入了一个新的功能称为vararg(动态参数),让我们来看看示例
class Lists {
public static <T> List<T> toList(T… arr) {
        List<T> lists = new ArrayList<T>();
        for(T element : arr) {
            lists.add(element);
}
return lists;
}
}
Lists<Integer> ints = Lists.toList(1,2,3);
我们看到”…”就表示方法接受动态参数,其实在运行时的时候,调用方法的参数,也是被打包成一个数组传入,只不过这一次是jvm帮我们做了。
所以我们也可以采用以下的方法进行调用:
Lists<Integer> ints = Lists.toList(new Integer[]{1,2,3});

不过在使用vararg功能时,需要留意的是,当方法中待传入的参数除了动态参数外,还有其它参数,则必须将动态参数方法在参数列表的最后面,例如:
public static <T> void addAll(List<T> list, T… arr);

(3) 调用泛型方法时显式给定类型参数的问题
我们在调用泛型方法时,还有一个要注意的地方是,是否在调用时显式地写明类型参数(type parameter),例如:
<1>List<Integer> ints = Lists<Integer>.toList();
<2>List<Object> objs = Lists<Object>.toList(1, “abc”);
一般的情况下,其实都不需要显式地指明类型参数,但对于上面的两种情况,可能就非常有必要。
上面的<1>式,我们没有传入任何参数,这样的话,类型推断算法就无法确定在方法内部的类型是什么了。
上面的<2>式,我们第一个参数传入整数,第二个参数传入字符串,你可能会认为,类型推断算法应该会推断出Integer及String的基类是Object,但是Integer及String,同时实现了Serializable和Comparable接口,这样类型推断算法就不能在这三者中作出正确的选择了。