Java 学习之路 之 类型通配符(四十一)

正如前面讲的,当使用一个泛型类时(包括声明变量和创建对象两种情况),都应该为这个泛型类传入一个类型实参。如果没有传入类型时间参数,编译器就会提出泛型警告。假设现在需要定义一个方法,该方法里有一个集合形参,集合形参的元素类型是不确定的,那应该怎样定义呢?

考虑如下代码:

public void test(List c){
  for (int i = 0; i < c.size(); i++){
    System.out.println(c.get(i));
  }
}
上面程序当然没有问题:这个一段最普通的遍历 List 集合的代码。问题是上面程序中 List 是一个有泛型声明的接口,此处使用 List 接口时没有传入实际类型参数,这将引起泛型警告。为此,我们考虑为 List 接口传入实际的类型参数----因为 List 集合里的元素类型是不确定的,将上面的方法改为如下形式:

public void test(List<Object> c){
  for(int i = 0; i < c.size(); i++){
    System.out.println(c.get(i));
  }
}
表面上看起来,上面方法声明没有问题,这个方法声明确实没有任何问题。问题是调用该方法传入的实际参数值时可能不是我们所期望的,例如,下面代码试图调用该方法。

// 创建一个 List<String> 对象
List<String> strList = new ArrayList<>();
// 将 strList 作为参数来调用前面的 test 方法
test(strList);//1
编译上面程序,将在 1 处发生如下编译错误:

无法将 Test 中的 test(java.util.List<java.lang.Object>) 应用于 (java.util.List<java.lang.String>)
上面程序出现了编译错误,这表明 List<String> 对象不能被当成 List<Object> 对象使用,也就是说,List<String> 类并不是 List<Object> 类的子类。

如果 Foo 是 Bar 的一个子类型(子类或者子接口),而 G 是具有泛型声明的类或接口,G<Foo> 并不是 G<Bar> 的子类型!这一点非常值得注意,因为它与我们的习惯看法不同。

与数组进行对比,先看一下数组是如何工作的。在数组中,程序可以直接把一个 Integer[] 数组赋给一个 Number[] 变量。如果试图把一个 Double 对象保存到该 Number[] 数组中,编译可以通过,但在运行时抛出 ArrayStoreException 异常。例如如下程序。

package com.sym.demo4;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值