Java泛型(2)泛型实参的限定

1.官方文档

https://docs.oracle.com/javase/tutorial/java/generics/bounded.html

2.作用

        有时候为减少不必要的转换和运行时错误发生。可以对泛型形参使用 extends X 语句,指定泛型实参必需为X及其子类,那么潜在的错误在编译时就可以发现。

  • extends X 限定泛型实参为X及其子类型。好处是可以确定调用X的某些行为(函数)一定存在。
  • 可以限定一个类类型,多个接口类型,它们之间用 & 相连。
  • 类类型必需是第1个
  • super 不能用在泛型形参声明时进行限制,如class MyNum<T super Integer>{},super只能用在通配符中进行限制。
  • 如有多个泛型形参,每个泛型形参都可以使用extends

3.泛型类中泛型形参 extends

3.1 简单示例

    interface I1{}
    interface I2{}
    interface I3{}
    interface I4 extends I2{}
    @Test
    public void bounded_test2(){
        class A {}
        abstract class B{}
        //class C <T extends Number & B >   {}  //error : 只能有一个类类型 限定
        class D <T extends B & I1 & I2 & I3>{}  //ok
        class E <T extends I4 & I2>         {}  //ok    :  接口重复
        class F <T extends I1 , I2,无dfo3 > {}  //error :  编译通过,但是只限定了I1,多个限定类之间用“&”,其中“,”后面的字符无意义
        class G <T extends I1 , K extends A>{}  //ok    :  多个泛型形参时,可分别extends限定。
    }

3.1 使用extends限制的好处示例

public class NaturalNumber<T extends Integer> {

    private T n;

    public NaturalNumber(T n)  { this.n = n; }

    public boolean isEven() {
        return n.intValue() % 2 == 0;
    }

    // ...
}

T被限制为Integer后,那么第8行的 n.intValue() 调用一定存在。

3.3 extends 泛型类型 及 多类型限制

    @Test
    public void wildcards_test4(){
        class MyNumber extends Number implements Serializable,Comparable<MyNumber>{
            @Override public int compareTo(MyNumber o)  { return this.intValue() - o.intValue(); }
            @Override public int    intValue        ()  { return 0; }
            @Override public long   longValue       ()  { return 0; }
            @Override public float  floatValue      ()  { return 0; }
            @Override public double doubleValue     ()  { return 0; }
        }
        class MyInteger extends Number{
            @Override public int    intValue        () { return 0; }
            @Override public long   longValue       () { return 0; }
            @Override public float  floatValue      () { return 0; }
            @Override public double doubleValue     () { return 0; }
        }
        class MyByte  extends Number implements     Comparable{             //warning,raw type
            @Override public int    intValue        () { return 0; }
            @Override public long   longValue       () { return 0; }
            @Override public float  floatValue      () { return 0; }
            @Override public double doubleValue     () { return 0; }

            @Override public int compareTo(Object   o) { return 1; }        //这里意义,与Object比较
        }
        class MyFloat extends Number implements     Comparable<Float>{      //warning,raw type
            @Override public int    intValue        () { return 0; }
            @Override public long   longValue       () { return 0; }
            @Override public float  floatValue      () { return 0; }
            @Override public double doubleValue     () { return 0; }

            @Override public int compareTo(Float    o) { return floatValue() > o ? 1 : (floatValue() == 0 ? 0 : -1); }
        }
        //ArrayList<? extends Number & Serializable> ee;                //error
        class A  <T extends Number & Serializable & Comparable<?>> {}   //ok,
        class B  <T extends Number & Serializable & Comparable<T>> {}   //ok
        class C  <T extends Number & Serializable & Comparable   > {}   //warning,raw type

        A<MyNumber>     am = new A<>();
        //A<MyInteger>  ai = new A<>();                 //error,MyInteger不是Comparable<?>
        //A<MyByte>     ab = new A<>();                 //error,MyByte不是Comparable<?>
        A<MyFloat>      af = new A<>();

        //B<String>     bm = new B<>();                 //error String 不是number
        //B<MyInteger>  bi = new B<>();                 //error,MyInteger没有实现Comparable<MyInteger>
        //B<MyFloat>    bf = new B<>();                 //error,MyFloat没有实现Comparable<MyFloat>
        //B<MyByte>     bb = new B<>();                 //error,MyByte实现的是Comparable<MyByte>
        B<MyNumber>     bn = new B<>();                 //ok

        //C<MyInteger>  ci = new C<>();                 //error,MyInteger没有实现Comparable
        C<MyByte>       cb = new C<>();                 //ok
        C<MyNumber>     cn = new C<>();                 //ok
        C<MyFloat>      cf = new C<>();                 //ok
    }

4.泛型函数中泛型形参 extends

@Test
    public void bounded_test3(){
        class A implements Comparable<A> {
            private final int value;
            public A(int x){
                value = x;
            }
            public <T extends Number> void foo(T t){
                System.out.println("T = " + t.getClass().getSimpleName());
            }
            public <T extends Comparable<T>> int greaterThan(T []array,T x){
                int count = 0;
                for (T t : array){
                    /*if (t > x){                //error : 只有Number类型和基本类型可以使用 比较运算符
                        ++count;
                    }*/
                    if (t.compareTo(x) > 0){
                        ++count;
                    }
                }
                return count;
            }

            @Override
            public int compareTo(A o) {
                return this.value - o.value;
            }
            @Override
            public String toString() {
                return "A{" + value + '}';
            }
        }
        A obj = new A(2);

        obj.foo(1)             ;
        obj.<Float>foo(1f)     ;
        //obj.<A>foo(obj)      ;            //error : A 不是 Number的子类。
        //obj.foo("str");      ;            //error : "str" 不是 Number


        A [] array = new A[]{new A(1),new A(2),new A(3),new A(4)};
        int count = obj.greaterThan(array,obj);

        System.out.println(String.format("there are %d elements greater than %s",count,obj));

    }

其中

  • 第11行的greaterThan泛型函数使用了extends语句,限制了泛型实参的类型为Comparable及子类,确保了 compareTo() 比较函数一定存在。
  • 第14行编译时会出错,因为只有Number类型和基本类型可以使用 比较运算符。无法确保T一定是Number类型。

运行结果

T = Integer
T = Float
there are 2 elements greater than A{2}

5.泛型类之间的继承关系

5.1 泛型类型相同,泛型实参不同

泛型类型相同且泛型形参无通配符,泛型实参为继承关系时,它们组成的参数化类型(parameterized type)不为继承关系。

如,Box<Integer>与Box<Number>,Integer是Number的子类,但是Box<Integer>却不是的Box<Number>子类,但都是Object的子类。

示例代码如下:

    @Test
    public void test_inheritance1(){
        class A<T>              {}
        class B<T> extends A<T> {}

        Object     object;
        A<Number>  an = new A<>();
        B<Integer> bi = new B<>();

        //an    = bi;           //error,
        object  = an;           //ok
        object  = bi;           //ok
    }

5.2 泛型实参相同,泛型类型不同

泛型实参相同,继承关系由泛型类型决定。

如Collection<String>,List<String>,ArrayList<String>,泛型实参都是String,这时它们为继承关系。

示例代码如下:

    @Test
    public void test_inheritance2(){
        class A<T>              {}
        class B<T> extends A<T> {}

        Object     object;
        A<Number>  an = new A<>();
        B<Number>  bn = new B<>();

        an      = bn;           //ok
        object  = an;           //ok
        object  = bn;           //ok
    }

5.3 多个泛型参形与继承关系

当泛型类型有多个泛型形参时,泛型实参由声明时传给父泛型类型的泛型形参决定。继承关系如上两节.

在 class MyList<T,U> extends ArrayList<T> {} 中,这里声明把第1个泛型形参T传给ArrayList<T>.

详细示例如下:

    @Test
    public void test_inheritance3(){

        class MyList<T,U> extends ArrayList<T> {}

        MyList   <String,Number >   myList1 = new MyList<>();
        MyList   <String,Integer>   myList2 = new MyList<>();
        MyList   <Number,Integer>   myList3 = new MyList<>();
        ArrayList<String >          list1   = new ArrayList<>();
        ArrayList<Number >          list2   = new ArrayList<>();
        Object                      obj     ;

        list1   =  myList1   ;      //ok    , myList1与list1 的泛型实参都是String,因为MyList把第1个泛型实参传给ArrayList<T>
        list1   =  myList2   ;      //ok    , 泛型实参同是string,且ArrayList是MyList的父类
        list2   =  myList1   ;      //error , 泛型实参不同,泛型类型也不同。
        list2   =  myList3   ;      //ok    , 泛型实参同是Number,且ArrayList是MyList的父类
        myList1 =  myList2   ;      //error , 泛型类型相同,但是第2个泛型实参不同,虽然它们为继承关系.
        
        obj     =  list1     ;      //ok
        obj     =  list2     ;      //ok
        obj     =  myList1   ;      //ok
        obj     =  myList2   ;      //ok
        obj     =  myList3   ;      //ok
    }

6. super 不限制泛型形参

    @Test
    public void bounded_test4(){
        //class MyNum <T super Integer>{   }    //error : super 不在泛型声明时对泛型形参限制
        List<? super Number> ints           ;   //ok    : 与通配符一起使用,限制类型为Number的父类。
        ints = new ArrayList<Object>()      ;   //ok    : Object是 Number父类。
        //ints = new LinkedList<Integer>()  ;   //error : Integer 不是 Number父类
    }

 

posted @ 2015-07-25 18:42  f9q  阅读(575)  评论(0编辑  收藏  举报