开发者社区> 问答> 正文

聊聊通配符吧

聊聊通配符吧

展开
收起
问问小秘 2020-06-23 14:45:00 1173 0
1 条回答
写回答
取消 提交回答
  • 通配符类型中,允许类型参数变化。比如,通配符类型:

    Couple<? extends Singer>
    

    表示任何泛型类型,它的类型参数是Singer的子类,如Couple,但不会是Couple

    假如现在我们需要编写一个方法去打印一些东西:

    public static void printCps(Couple<Rapper> cps) {
          Rapper one = cp.getOne();
          Rapper two = cp.getTwo();
          System.out.println(one.getName() + " & " + two.getName() + " are cps.");
    }
    

    正如前面所讲到的,不能将Couple传递给这个方法,这一点很受限制。解决的方案很简单,使用通配符类型:

    public static void printCps(Couple< ? extends Singer> cps) 
    

    CoupleCouple< ? extends Singer>的子类型。

    我们接下来来考虑另外一个问题,使用通配符会通过Couple< ? extends Singer>的引用破坏Couple吗?

    Couple<Rapper> rapper = new Couple<>(rapper1, rapper2);
    Couple<? extends Singer> singer = rapper;
    player.setOne(reader);
    

    这样可能会引起破坏,但是当我们调用setOne的时候,如果调用的不是Singer的子类Rapper类的对象,而是其他Singer子类的对象,就会出错。我们来看一下Couple的方法:

    ? extends Singer getOne();
    void setOne(? extends Singer);
    

    这样就会看的很明显,因为如果我们去调用setOne()方法,编译器之 可以知道是某个Singer的子类型,而不能确定具体是什么类型,它拒绝传递任何特定的类型,因为 ? 不能用来匹配。但是使用getOne就不存在这个问题,因为我们无需care它获取到的类型是什么,但一定是Singer的子类。

    通配符限定与类型变量限定非常相似,但是通配符类型还有一个附加的能力,即可以指定一个超类型限定:

    ? super Rapper
    

    这个通配符限制为**Rapper的所有父类,为什么要这么做呢?带有超类型限定的通配符的行为与子类型限定的通配符行为完全相反,可以为方法提供参数,但是却不能获取具体的值,即访问器是不安全的,而更改器方法是安全的**:

    编译器无法知道setOne方法的具体类型,因此调用这个方法时不能接收类型为SingerObject的参数。只能传递Rapper类型的对象,或者某个子类型(Reader)对象。而且,如果调用getOne,不能保证返回对象的类型。

    总结一下:

    带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。

    2020-06-23 14:45:27
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载