Java泛型:多个边界

时间:2015-05-20 07:36:05

标签: java generics

我有这段代码:

public class Test {

    public static void main(String[] args) {
        Test t = new Test();
        t.callTest();
    }

    public void callTest() {
        GenericTest gt = new GenericTest<Date>(); // this line don't compile
        gt.test(new Date());
    }

    class GenericTest<T extends Date & List> {
        T x;

        public void test(T y) {
            System.out.println(x.toString());
        }
    }
}

我理解为什么new GenericTest<Date>()不能编译,这是因为Date没有实现List接口,但是如果我没有泛型实例化GenericTest gt = new GenericTest(),整个代码都有效,我不明白为什么。方法测试期望(T y)位于T extends Date并实现List,但它适用于gt.test(new Date())

3 个答案:

答案 0 :(得分:16)

当您实例化时:

CREATE TRIGGER PrecioCompra After Insert or Update ON "Compra" 

您使用GenericTest gt = new GenericTest() 类型的原始版本。这意味着GenericTest类型将被第一个绑定(在您的情况下为T)替换。这就是为什么Date的方法合约具有GenericTest#test()参数,而不是Date参数的原因。

请注意,除第一个绑定外,每个绑定都必须是一个接口。只有第一个绑定可以成为一个类。这样做的原因是它不可能有类型,它继承了超过一个超类。

因此,由于只有第一个参数是一个类,因此您无法切换类型参数,并且以下类定义将无效:

List

答案 1 :(得分:0)

错误是因为在编译时使用通用代码进行了更严格的类型检查,并且在给定的代码中使用了参数化类型。

正如在问题中提到的GenericTest gt = new GenericTest()编译并执行,仅是因为在这里toString()方法被调用。如果是某些List接口方法,则执行时将出现ClassCastException。让我们说一下size()。

class GenericTest<T extends Date & List> {
        public void test(T y) {
            System.out.println(y.size()); // ClassCastException
        }
}

答案 2 :(得分:-2)

如果创建没有泛型参数的泛型类实例,编译器会发出警告,并且不再控制已创建实例的使用情况。至于为什么代码在没有声明泛型类型的情况下工作 - 因为在这种情况下T被假定为Object,那就是任何类型都是好的