java泛型

推荐命名类型参数

K —— 键,比如映射的键。 

V —— 值,比如 List 和 Set 的内容,或者 Map 中的值。 

E —— 异常类。 

T —— 泛型。

 

泛型不是协变的

List<Object> 不是 List<String> 的父类型。

对于数组,如果 A 扩展 B,那么 A 的数组也是 B 的数组,并且完全可以在需要 B[] 的地方使用 A[]:

Integer[] intArray = new Integer[10]; 
Number[] numberArray = intArray;

上面的代码是有效的,因为Integer是Number的子类。

但是对于泛型来说则不然。下面的代码是无效的:

List<Integer> intList = new ArrayList<Integer>();
List<Number> numberList = intList; // invalid

大多数 Java 程序员觉得这缺少协变很烦人,或者甚至是坏的,但是之所以这样有一个很好的原因。

如果可以将 List<Integer> 赋给 List<Number>,下面的代码就会违背泛型应该提供的类型安全:

List<Integer> intList = new ArrayList<Integer>();
List<Number> numberList = intList; // invalid
numberList.add(new Float(3.1415));

因为 intList 和 numberList 都是有别名的,如果允许的话,上面的代码就会让您将不是 Integers 的东西放进 intList 中。

 

类型通配符

void printList(List<Object> l) { 

for (Object o : l) 

    System.out.println(o); 

}

编译不过,因为一个 List<Integer> 不是一个 List<Object>(泛型不是协变的)。

现在您的泛型版本还没有普通的非泛型版本有用!

 

解决方案是使用类型通配符:

void printList(List<?> l) { 

for (Object o : l) 

    System.out.println(o); 

}

上面代码中的问号是一个类型通配符。

List<?> 是任何泛型 List 的父类型,所以您完全可以将 List<Object>、List<Integer> 或 List<List<List<Integer>>> 传递给 printList()。

 

类型通配符的作用

可以从中检索元素,但是不能添加元素。

原因是变化的方法比不变化的方法需要更多的类型信息。

下面的代码则工作得很好:

List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
System.out.println(lu.get(0));

为什么该代码能工作呢?对于 lu,编译器一点都不知道 List 的类型参数的值。但是编译器比较聪明,它可以做一些类型推理。

 

下面的代码不能工作:

List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
lu.add(new Integer(43)); // error

对于 lu,编译器不能对 List 的类型参数作出足够严密的推理,以确定将 Integer 传递给 List.add() 是类型安全的。所以编译器将不允许您这么做。

 

请注意下面的代码将能工作,因为它不依赖于编译器必须知道关于 lu 的类型参数的任何信息:

List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(42));
List<?> lu = li;
lu.clear();

 

限制类型

在泛型方法的例子中,类型参数 V 是无约束的或无限制的 类型。有时需要对类型参数指定附加的约束。

例子 Matrix 类,它使用类型参数 V,该参数由 Number 类来限制:

public class Matrix<V extends Number> { ... }

编译器允许您创建 Matrix<Integer> 或 Matrix<Float> 类型的变量,但是如果您试图定义 Matrix<String> 类型的变量,则会出现错误。

类型参数 V 被判断为由 Number 限制 。

在没有类型限制时,类型参数由 Object 限制。

 

泛型方法

public class GenMethod {
    public static <T> void display(T t) {
        System.out.println(t.getClass());
    }
}

 

泛型类

public interface Map<K,V> {
	V put(K key, V value);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值