Java泛型的应用——T extends Comparable<? super T>

  在观察Java源码的时候,发现了这么一个写法T extends Comparable<? super T>。不禁纳闷为什么要这么写呢?有什么好处吗,extends和super在这里的作用着实让人有点不清楚。

  接下来,我将结合代码跟大家分享一下我关于这里泛型应用的看法。

  

  1.  <T extends Comparable<? super T>>代表什么意思

  • 大家可以明白的是这里应用到了Java的泛型,那么首先向大家说明一下这里extends的作用

  extends后面跟的类型,如<任意字符 extends 类/接口>表示泛型的上限。示例代码如下:

import java.util.*;
class Demo<T extends List>{}
public class Test
{
    public static void main(String[] args) {
    Demo<ArrayList> p = null; // 编译正确
//这里因为ArrayList是List的子类所以通过
//如果改为Demo<Collection> p = null;就会报错这样就限制了上限
    }
}
  • 在理解了extends所表示的泛型的上限后,接下来介绍一下super的作用,它与extends相反,表示的是泛型的下限。
  • 所以结合上述两点,我们来分析一下这句话整体代表什么意思。首先,extends对泛型上限进行了限制即T必须是Comparable<? super T>的子类,然后<? super T>表示Comparable<>中的类型下限为T!

 

  2.  <T extends Comparable<T>> 和 <T extends Comparable<? super T>> 有什么不同

  接下来我们通过对比,使得大家对为何要这样编写代码有更加深刻的印象。

  • <T extends Comparable<T>>

  它代表的意思是:类型T必须实现Comparable接口,并且这个接口的类型是T。这样,T的实例之间才能相互比较大小。这边我们以Java中GregorianCalendar这个类为例。

  代码如下所示:

import java.util.GregorianCalendar;
class Demo<T extends Comparable<T>>{}
//注意这里是没有? super的
public class Test
{
    public static void main(String[] args) {
       Demo<GregorianCalendar> p = null;
        }
}

  这里编译报错,因为这里的<T extends Comparable<T>>相当于<GregorianCalendar extends Comparable<GregorianCalendar>>,但是GregorianCalendar中并没有实现Comparable<GregorianCalendar>,而是仅仅持有从Calendar继承过来的Comparable<Calendar>,这样就会因为不在限制范围内而报错。

  • <T extends Comparable<? super T>>  

  它代表的意思是:类型T必须实现Comparable接口,并且这个接口的类型是T或者是T的任一父类。这样声明后,T的实例之间和T的父类的实例之间可以相互比较大小。同样还是以GregorianCalendar为例。代码如下所示:

import java.util.GregorianCalendar;

class Demo<T extends Comparable<? super T>>{}

public class Test1
{
    public static void main(String[] args) {
       Demo<GregorianCalendar> p = null; // 编译正确
    }
}  

  此时编译通过,这里可以理解为<GregorianCalendar extends Comparable<Calendar>>!因为Calendar为GregorianCalendar 的父类并且GregorianCalendar 实现了Comparable<Calendar>,具体可以在API中进行查看!

  3. 实例代码演示

  代码如下所示:

 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;

 public class Test
 {
     //第一种声明:简单,灵活性低
     public static <T extends Comparable<T>> void mySort1(List<T> list)
     {
         Collections.sort(list);
     }

     //第二种声明:复杂,灵活性高
     public static <T extends Comparable<? super T>> void mySort2(List<T> l)
     {
         Collections.sort(list);
     }

     public static void main(String[] args)
     {
         //主函数中将分别创建Animal和Dog两个序列,然后调用排序方法对其进行测试     //main函数中具体的两个版本代码将在下面具体展示
     }
 }

 class Animal implements Comparable<Animal>
 {
     protected int age;

     public Animal(int age)

     {
         this.age = age;
     }

     //使用年龄与另一实例比较大小
     @Override
     public int compareTo(Animal other)
     {
         return this.age - other.age;
     }
 }

 class Dog extends Animal
 {
     public Dog(int age)
     {
         super(age);
     }
 }

上面的代码包括三个类:

  1. Animal实现了Comparable<Animal>接口,通过年龄来比较实例的大小
  2. Dog从Animal继承,为其子类。
  3. Test类中提供了两个排序方法和测试用的main()方法:
    • mySort1()使用<T extends Comparable<T>>类型参数
    • mySort2()使用<T extends Comparable<? super T>>类型参数
    • main()测试方法。在这里将分别创建Animal和Dog两个序列,然后调用排序方法对其进行测试。

  3.1 对mySort1()进行测试,main方法代码如下所示:

// 创建一个 Animal List
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Animal(25));
animals.add(new Dog(35));

// 创建一个 Dog List
List<Dog> dogs = new ArrayList<Dog>();
dogs.add(new Dog(5));
dogs.add(new Dog(18));

// 测试  mySort1() 方法
mySort1(animals);
mySort1(dogs);

  结果编译出错,报错信息为:

The method mySort1(List<T>) in the type TypeParameterTest is not applicable for the arguments (List<Dog>)

  mySort1() 方法的类型参数是<T extends Comparable<T>>,它要求的类型参数是类型为T的Comparable。

  如果传入的是List<Animal>程序将正常执行,因为Animal实现了接口Comparable<Animal>。

  但是,如果传入的参数是List<Dog>程序将报错,因为Dog类中没有实现接口Comparable<Dog>,它只从Animal继承了一个Comparable<Animal>接口。

  注意:animals list中实际上是包含一个Dog实例的。如果碰上类似的情况(子类list不能传入到一个方法中),可以考虑把子类实例放到一个父类 list 中,避免编译错误。

  3.2 对mySort12()进行测试,main方法代码如下所示:

public static void main(String[] args)
{
    // 创建一个 Animal List
    List<Animal> animals = new ArrayList<Animal>();
    animals.add(new Animal(25));
    animals.add(new Dog(35));

    // 创建一个 Dog List
    List<Dog> dogs = new ArrayList<Dog>();
    dogs.add(new Dog(5));
    dogs.add(new Dog(18));

    // 测试  mySort2() 方法
    mySort2(animals);
    mySort2(dogs);
}

  这时候我们发现该程序可以正常运行。它不但能够接受Animal implements Comparable<Animal>这样的参数,也可以接收:Dog implements Comparable<Animal>这样的参数。

  3.3 是否可以通过将Dog实现Comparable<Dog>来解决问题?

  由分析可得程序出现问题是因为Dog类没有实现接口Comparable<Dog>,那么我们能否将该类实现接口Comparable<Dog>来解决问题呢?

  代码如下所示:

class Dog extends Animal implements Comparable<Dog>
{
    public Dog(int age)
    {
        super(age);
    }
}

  结果程序编译报错,错误信息如下所示:

The interface Comparable cannot be implemented more than once with different arguments: Comparable<Animal> and Comparable<Dog>

  意义是Dog类已经从Animal中继承了Comparable该接口,无法再实现一个Comparable。

  若子类需要使用自己的比较方法,则需要重写父类的public int CompareTo(Animal other)方法。

  4. 总结 

  对Animal/Dog这两个有父子关系的类来说:<T extends Comparable<? super T>>可以接受List<Animal>,也可以接收 List<Dog> 。而<T extends Comparable<T>>只可以接收 List<Animal>所以,<T extends Comparable<? super T>>这样的类型参数对所传入的参数限制更少,提高了 API 的灵活性。总的来说,在保证类型安全的前提下,要使用限制最少的类型参数。

  

  

  

  

时间: 2024-08-25 02:50:31

Java泛型的应用——T extends Comparable<? super T>的相关文章

Java范型之T extends Comparable&lt;? super T&gt;

在观察Java源码的时候,发现了这么一个写法T extends Comparable<? super T>.不禁纳闷为什么要这么写呢?有什么好处吗,extends和super在这里的作用着实让人有点不清楚. 接下来,我将结合代码跟大家分享一下我关于这里泛型应用的看法. 1.<T extends Comparable<? super T>>代表什么意思 大家可以明白的是这里应用到了Java的泛型,那么首先向大家说明一下这里extends的作用 extends后面跟的类型,

&lt;T extends Comparable&lt;? super T&gt;&gt;

在看Collections源代码中,看到如下代码: [java] view plain copy public static <T extends Comparable<? super T>> void sort(List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.l

如何理解 Java 中的 &lt;T extends Comparable&lt;? super T&gt;&gt;

1 <T extends Comparable<T>> 和 <T extends Comparable<? super T>> 有什么不同 <T extends Comparable<T>> 类型 T 必须实现 Comparable 接口,并且这个接口的类型是 T.只有这样,T 的实例之间才能相互比较大小.例如,在实际调用时若使用的具体类是 Dog,那么 Dog 必须 implements Comparable<Dog>

&lt;T extends Comparable&lt;T&gt;&gt;和&lt;T extends Comparable&lt;? super T&gt;&gt;含义

<T extends Comparable<T>>表明T实现了Comaprable<T>接口,此条件强制约束,泛型对象必须直接实现Comparable<T>(所谓直接就是指不能通过继承或其他方式) <T extends Comparable<? super T>> 表明T的任意一个父类实现了Comparable<? super T>接口,其中? super T表示 ?泛型类型是T的父类(当然包含T),因此包含上面的限制条件

public static &lt;T extends Comparable&lt;? super T&gt;&gt; void sort (List&lt;T&gt; list)的理解

public static <T extends Comparable<? super T>> void sort (List<T> list)的理解 public static <T extends Comparable<? super T>> void sort (List<T> list) (1)首先:public static void sort(List list) (2)为了安全性加泛型:public static <

java泛型小问题

几年前当Java5还未正式发布的时候,看到过一些人写的介绍Tiger中的新特性,当时对我第一感觉冲击最大的就是泛型(generics)和注释(annotation),因为它们直接影响了我们编码的语法习惯. 在后来的使用过程中,对于泛型一直没有特别深入的使用过,没有遇到那样的需求和场景.只需要了解Java中的泛型是编译期的,运行期被“擦拭”掉了:然后还有几种通配符的表示就足够了. 直到一天我在查看Java5中Enum的源代码时,发现它是这么定义的: Java代码 public abstract c

Java-泛型编程-使用通配符? extends 和 ? super

泛型中使用通配符有两种形式:子类型限定<? extends xxx>和超类型限定<? super xxx>. (1)子类型限定 下面的代码定义了一个Pair<T>类,以及Employee,Manager和President类. public class Pair<T> { private T first; private T second; public Pair(T first, T second) { this.first = first; this.s

java泛型通配符?

转自:http://www.linuxidc.com/Linux/2013-10/90928.htm T  有类型 ?  未知类型 一.通配符的上界 既然知道List<Cat>并不是List<Anilmal>的子类型,那就需要去寻找替他解决的办法, 是AnimalTrianer.act()方法变得更为通用(既可以接受List<Animal>类型,也可以接受List<Cat>等参数).在java里解决办法就是使用通配符"?",具体到Anim

Java 泛型、通配符? 解惑

Java 泛型通配符?解惑 分类: JAVA 2014-05-05 15:53 2799人阅读 评论(4) 收藏 举报 泛型通配符上界下界无界 目录(?)[+] 转自:http://www.linuxidc.com/Linux/2013-10/90928.htm T 有类型 ? 未知类型 一.通配符的上界 既然知道List<Cat>并不是List<Anilmal>的子类型,那就需要去寻找替他解决的办法, 是AnimalTrianer.act()方法变得更为通用(既可以接受List&