java 泛型问题

本问题需要对泛型有深刻了解,原理题主明白,只是不明白我下面说明的这个问题

代码如下

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>这一条件呀

请指教,谢谢

阅读 1.9k
1 个回答

都会检查,只是要求不同。

方法的泛型参数其实会在两个地方检查:在调用时和获取返回值时。

你的例子里面仅调用了方法,并没有获取它的返回值,因此只检查了一次。

对调用参数的检查是相对宽松的,它仅会检查传入的参数是否符合方法泛型的下界

而对返回值的检查就比较严格了,它会检查返回值的接收类型是否符合方法泛型的上界。这一点与声明类对象的时候是一样的。

具体来说,当调用方法的时候,如果我传入的是一个Square,但方法泛型要求的是一个Shape(通过<AnyType extends Comparable<AnyType>>)。这种时候是可以通过编译的,因为编译器会把这个Square参数当做Shape对待,也就是向上转型。这是完全没有问题的,因为任何Shape的子类都是Shape

但是,当获取返回值的时候就不同了,如果你用一个Shape变量获取,这是没有问题的,因为它本身就符合泛型的要求。但如果你用一个Square变量来获取就不行了,因为这样定义的方法它只能返回Shape,因此无法自动向下转型为Square

声明类对象的时候与获取方法返回值是同样的道理。

所以在你的例子中,修改后,声明类对象无法通过编译,但方法调用可以。如果你测试返回值,你会发现与类对象的声明的情况是相同的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题