本问题需要对泛型有深刻了解,原理题主明白,只是不明白我下面说明的这个问题
代码如下
public class Shape implements Comparable<Shape> {
@Override
public int compareTo(Shape o) {
return 0;
}
}
public class Square extends Shape {
}
public class TestGenetic {
public static <AnyType extends Comparable<? super AnyType>> AnyType findMax(AnyType[] arr){
int maxIndex=0;
for (int i = 0; i <arr.length ; i++) {
if (arr[i].compareTo(arr[maxIndex+1])>0)
maxIndex=i;
}
return arr[maxIndex];
}
public static void main(String[] args) {
Shape[] shapes={new Shape(),new Shape()};
Square[] squares={new Square(),new Square()};
findMax(shapes);
findMax(squares);
}
}
若修改一下泛型泛型方法中的泛型:
public class TestGenetic {
public static <AnyType extends Comparable<AnyType>> AnyType findMax(AnyType[] arr){
int maxIndex=0;
for (int i = 0; i <arr.length ; i++) {
if (arr[i].compareTo(arr[maxIndex+1])>0)
maxIndex=i;
}
return arr[maxIndex];
}
public static void main(String[] args) {
Shape[] shapes={new Shape(),new Shape()};
Square[] squares={new Square(),new Square()};
findMax(shapes);
findMax(squares);
}
}
同样不会报错
但是,在泛型类中则不是这样
public class TestGeneric1<AnyType extends Comparable<? super AnyType>> {
public static void main(String[] args) {
TestGeneric1<Square> p=null;
}
}
这种不会报错,但是,如果我修改一下泛型,如下:
public class TestGeneric1<AnyType extends Comparable<AnyType>> {
public static void main(String[] args) {
TestGeneric1<Square> p=null;//编译报错
}
}
则编译报错,请问为什么在泛型类中会进行泛型检查,而泛型方法中不进行检查呢,在泛型方法中,Square明明不符合AnyType extends Comparable<AnyType>这一条件呀
请指教,谢谢
都会检查,只是要求不同。
方法的泛型参数其实会在两个地方检查:在调用时和获取返回值时。
你的例子里面仅调用了方法,并没有获取它的返回值,因此只检查了一次。
对调用参数的检查是相对宽松的,它仅会检查传入的参数是否符合方法泛型的
下界
。而对返回值的检查就比较严格了,它会检查返回值的接收类型是否符合方法泛型的
上界
。这一点与声明类对象的时候是一样的。具体来说,当调用方法的时候,如果我传入的是一个
Square
,但方法泛型要求的是一个Shape
(通过<AnyType extends Comparable<AnyType>>
)。这种时候是可以通过编译的,因为编译器会把这个Square
参数当做Shape
对待,也就是向上转型。这是完全没有问题的,因为任何Shape
的子类都是Shape
。但是,当获取返回值的时候就不同了,如果你用一个
Shape
变量获取,这是没有问题的,因为它本身就符合泛型的要求。但如果你用一个Square
变量来获取就不行了,因为这样定义的方法它只能返回Shape
,因此无法自动向下转型为Square
。声明类对象的时候与获取方法返回值是同样的道理。
所以在你的例子中,修改后,声明类对象无法通过编译,但方法调用可以。如果你测试返回值,你会发现与类对象的声明的情况是相同的。