美文网首页Java 杂谈
CoreJava笔记 - 范型程序设计(4)

CoreJava笔记 - 范型程序设计(4)

作者: 杀死BL | 来源:发表于2018-07-26 10:07 被阅读2次

    通配符类型

    1. 什么是通配符类型
      EmployeeManager的超类。定义一个打印方法:public static void printBuddies(Pair<Employee>),但是无法将Pair<Manager>传参。这时应该采用通配符类型:public static void printBuddies(Pair<? extends Employee>)
      这种方式不会影响get方法,但是set方法可能会发生编译错误。

      总结:限定了子类型的通配符用于从范型对象读取。

    2. super bound
      限定了类型必须是某个类型的基类:public static void minmax(Manager[] a,Pair<? super Manager> result)。在这个例子中,传入的是Manager[],但是结果完全可以保存在Pair<Employee>或者Pair<Object>中。

      总结:带有超类型限定的通配符可以向范型对象写入。

      扩展阅读:一个变态一点儿的例子:

       声明函数:`public static <T extends Comparable> T min(T[] a)`。因为`Comparable`本身就是范型类,如果更讲究一点儿:`public static <T extends Comparable<T>> T min(T[] a)`。
      
       在大多数情况下,这段代码都工作得非常好,直到遇到`LocalDate`类,`LocalDate`实现了`ChronoLocalDate`接口,而`ChronoLocalDate`扩展了`Comparable<ChronoLocalDate>`接口。因此`LocalDate`实现的接口是`Comparable<ChronoLocalDate>`,而不是`Comparable<LocalDate>`。
      
       此时,函数应该声明为:`public static <T extends Comparable<? super T>> T min(T[] a)`,而接口中的方法声明为:`int compareTo(? super T)`。
      

    注意:子类型限定的一个常用用法是作为一个函数式接口的参数类型。如Collection接口的一个方法:
    default boolean removeIf(Predicate<? super E> filter)

    1. 无限定通配符
      无限定通配符Pair<?>在使用时会有比较严格的限定。? getFirst()是能返回Object类型,而setFirst(?)根本无法调用(除了以null作为参数)。
      使用无限定通配符的场景:

      // 在这个方法中,根本不涉及到类型T,因此用无限定通配符的可读性好一些
      public static boolean hasNulls(Pair<?> p) {
          return p.getFirst() == null || p.getSecond() == null;
      }
      // 范型版本的声明如下:
      public static <T> boolean hasNulls(Pair<T> p) {...}
      
    2. 通配符的捕获
      通配符广泛应用在范型库的开发中,但是通配符?不是一个合法的类型。如果需要用到类型T来捕获类型的值,就需要用到普通范型方法。
      看下面的例子:

      // 函数库中有交换函数,用逻辑上,交换过程不关心数据类型,但在交换过程中要暂时性的缓存一个数据。
      // 缓存的数据必须要保存在一个有明确类型的变量中。
      public static void swap(Pair<?> p) {swapHelper(p);}
      // 用普通范型方法swapHelper()
      public static <T> void swapHelper(Pair<T> p) {
          T t = p.getFirst();
          p.setFirst(p.getSecond());
          p.setSecond(t);
      } 
      

      上面的例子有个问题:它其实可以使用普通范型,根本不需要通配符。但是下面的例子则只能使用通配符了:

      // 不是minmax,而是maxmin。需要一次swap
      public static void maxminBonus(Manager[] a, Pair<? super Manager> result) {
          minmax(a, result);
          swap(result);
      }
      

    相关文章

      网友评论

        本文标题:CoreJava笔记 - 范型程序设计(4)

        本文链接:https://www.haomeiwen.com/subject/ckbvmftx.html