一、数组是协变的,泛型是非协变的。

例:如果存在一个方法Test1(Shape[] arr),并且存在一个类Square extends Shape,那么向Test1中传入一个Square[]能够通过编译。

但是如果存在方法Test2(Colleciton<Shape> arr),此时向Test2中传入一个ArrayList<Square>无法通过编译。

若要解决Test2所存在的问题,可以改变参数类型Test3(Collection<? extends Shape> arr)或者Test4(Collection<? super Shape> arr)

import java.util.*;

public class GenericTypeTest {
    public void TypeTest1(Shape[] arr) {
        System.out.println("Pass1.");
    }
    public void TypeTest2(Collection<? extends Shape> arr) {
        System.out.println("Pass2.");
    }
    public void TypeTest3(Collection<? super Square> arr) {
        System.out.println("Pass3.");
    }
    public void TypeTest4(Collection<Shape> arr) {
        System.out.println("Pass4.");
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Square[] sqs = {};
        ArrayList<Square> listSqs = new ArrayList<Square>();
        ArrayList<Shape> listSpe = new ArrayList<Shape>();
        ArrayList<LowSquare> listLow = new ArrayList<LowSquare>();
        GenericTypeTest genericTypeTest = new GenericTypeTest();
        genericTypeTest.TypeTest1(sqs);
        genericTypeTest.TypeTest2(listSqs);
        genericTypeTest.TypeTest3(listSpe);
        genericTypeTest.TypeTest2(listLow);
        //genericTypeTest.TypeTest4(sqs);    泛型是非协变的,编译失败
        //genericTypeTest.TypeTest3(listLow);    LowSquare不是Square的父类, 编译会失败
    }

}

 

二、类型限界(type bound)

类型限界用于指定参数必须具备的性质,在类名直接指定参数性质与在方法中指定参数性质均可。

假设Shape类实现了Comparable接口,<T extends Comparable<? super T>>表示参数本身类或者其父类必须实现Comparable接口。

如果只是单纯的<T extends Comparable<T>>,那么findMax方法只接收Shape类型的参数。

public class TypeBoundTest<T extends Comparable<? super T>>{
    
    public T findMax(T[] arr) {
        int maxIndex = 0;
        for(int i = 1; i < arr.length; i++) {
            if(arr[i].compareTo(arr[maxIndex]) > 0) 
                maxIndex = i;
        }
        return arr[maxIndex];
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Square[] arr = {new Square(1), new Square(2)};
        System.out.println(new TypeBoundTest<Square>().findMax(arr).val);
    }
}
public class TypeBoundTest {
    
    public <T extends Comparable<? super T>> T findMax(T[] arr) {
        int maxIndex = 0;
        for(int i = 1; i < arr.length; i++) {
            if(arr[i].compareTo(arr[maxIndex]) > 0) 
                maxIndex = i;
        }
        return arr[maxIndex];
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Square[] arr = {new Square(1), new Square(2)};
        System.out.println(new TypeBoundTest().findMax(arr).val);
    }
}