一、数组是协变的,泛型是非协变的。
例:如果存在一个方法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); } }