list 泛型_Java 泛型参数中通配符?和 Object 的差异

面向对象的设计有个基本原则:里氏代换原则,简单理解为凡是接受父类的场合,都可以接受其子类。

0f7333749b3aa5a324a243abe0efb8cb.png

OOP

Java 是一种面向对象的语言,也许很多同学并没有听说过所谓的里氏代换原则,但不妨碍大家应用这样的思维去进行开发,并形成了某种固有的认知——凡是需要父类的场合,我都可以传入子类。

正是这种思维定式,导致我们在理解泛型参数时遇到困难

泛型参数不适用里氏代换原则

如果你要传入的参数本身是个泛型参数,例如 List,Map 这类,那么目标泛型要求什么参数类型,你就要声明什么类型传给他,声明成子类后再传入是不行的,最典型的就是泛型参数为 Object 的时候

看个例子

public static final void print(List list) {    System.out.println(list);}public void test() {    List intList = Arrays.asList(1,2,3,4);    // 类型 List 和泛型参数 List 不一致, 编译不通过    print(intList);        List objList = Arrays.asList(1,2,3,4);    // 编译通过    print(objList);}

由于里氏代换原则的思维定式存在,有些同学想当然的认为 List 也是 List,实际上这种场景不适合里氏代换原则,泛型要的是 List,就只能传 List

泛型参数 ? 不表示任何类型

在使用 ? 作为泛型参数时,可以理解为 ? 是个通配符,任何类型都 ok,但本身不表示特定类型,这是它和 Object 的最大区别,如果用里氏代换原则来套这种场景,会觉得 ? 更像是所有类的父类,那不就表示 Object 类了吗?不能这样想,使用泛型时,抛开里氏代换的思维定式。

看个例子

public static final void print(List> list) {    System.out.println(list);}public void test() {    List intList = Arrays.asList(1,2,3,4);    // 编译通过    print(intList);        List objList = Arrays.asList(1,2,3,4);    // 编译通过    print(objList);        List strList = Arrays.asList("tom","jerry","mike");    // 编译通过    print(strList);}

可以发现,? 是来者不拒的

? 参数进阶

对于声明为 ? 的泛型,要注意:你没有办法定义一个类型为 ? 的对象,从而导致你无法调用那些需要传入泛型参数的方法,比如 List 的 add(E e),Map 的 put(K key, V value) 这类的方法

public void test() {    Listlist = new ArrayList<>();    list.add(1);    list.add(2);    list.add(3);        List> intList = list;    // 编译不通过,参数 4 的 类型不是 ?    intList.add(4);    // 参数 0 不需要泛型化,该方法正常执行    intList.remove(0);}

结语

其实也很简单,我们在面对泛型时,从里氏代换的思维定式里脱身出来,泛型里的一些难以理解之处就很简单了

无责任联想一下,也许一个刚接触 Java 语言的小白,更容易掌握泛型呢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值