泛型函数和通配符的选择

什么时候应当使用泛型函数,什么时候应当使用通配符呢?
先看一段来自Collection里的代码:
interface Collection<E> {
   public boolean containsAll(Collection<?> c);
   public boolean addAll(Collection<? extends E> c);
}
我们也可以用泛型函数改写:
interface Collection<E> {
   public <T> boolean containsAll(Collection<T> c);
   public <T extends E> boolean addAll(Collection<T> c);
}
在containsAll和addAll中,类型参数T仅仅被使用了一次。函数返回值并不依赖于类型参数。这就告诉我们,类型参数是被用于实现多态的;它的作用仅仅是允许不同的实际类型在不同的场合下可以被使用。如果是这种情况的话,应当使用通配符。通配符用来实现弹性的子类化——就像这里试图表达的那样。
泛型函数允许类型参数用来表达函数以及它的返回值和一个或多个类型参数之间的依赖性。如果,不存在这样的依赖性的话,泛型函数就不应当被使用。
泛型函数和通配符有时是可以一起使用的,如:
class Collections {
   public static <T> void copy(List<T> dest, List<? extends T> src) { … }
}
注意两个参数之间的类型依赖性。src内包含的对象必须满足is-a T,只有这样才能够被安全的插入dest,因为dest包含的对象是T类型的。当然这样也可以的:
public static <T, S extends T> void copy(List<T> dest, List<S> src) { … }
但是推荐第一种用法。因为T同时对dest和src起作用,而S仅仅作用于src,没有其他的什么依赖于它——这种情况下,用通配符取代S比较好。用通配符更加清晰、明了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值