简体   繁体   English

Java 泛型:多重边界

[英]Java Generics: Multiple Bounds

I have this code:我有这个代码:

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());
        }
    }
}

I understand why new GenericTest<Date>() doesn't compile, it is because Date doesn't implement List interface, but if I instantiate GenericTest gt = new GenericTest() without generic, the whole code works, and I don't understand why.我明白为什么new GenericTest<Date>()不能编译,那是因为 Date 没有实现 List 接口,但是如果我实例化GenericTest gt = new GenericTest()没有泛型,整个代码工作,我不明白为什么。 The method test expects (T y) where T extends Date and implements List , but it works with gt.test(new Date()) .方法 test 期望(T y)其中T extends Date并实现List ,但它适用于gt.test(new Date())

When you instantiate like this:当你像这样实例化时:

GenericTest gt = new GenericTest() 

you use the raw version of GenericTest type.您使用GenericTest类型的原始版本。 This means that T type will be replaced with it's first bound (in your case, Date ).这意味着T类型将被替换为它的第一个绑定(在您的情况下为Date )。 That's why the method contract of GenericTest#test() has a Date parameter, but not a List one.这就是为什么GenericTest#test()的方法契约有一个Date参数,而不是一个List参数。

Note that every bound, except the first one, must be an interface.请注意,除了第一个边界外,每个边界都必须是一个接口。 Only the first bound can be a class.只有第一个边界可以是一个类。 The reason for this is that it's not possible to have types, which inherit from more that one super-class.这样做的原因是不可能有从多个超类继承的类型。

So, since only the first parameter is a class, you won't be able to switch the type-parameters and the following class definition will be invalid:因此,由于只有第一个参数是类,因此您将无法切换类型参数,并且以下类定义将无效:

class GenericTest<T extends List & Date> { }

The error is because there is stronger type checks at compile time with generic code, and in the given code parameterized type is used.错误是因为在编译时使用泛型代码进行了更强的类型检查,并且在给定的代码中使用了参数化类型。

As mentioned in problem that the GenericTest gt = new GenericTest() compiles and executes, then it is only because here toString() method is being invoked.正如问题中提到的GenericTest gt = new GenericTest()编译和执行,那只是因为这里调用了 toString() 方法。 If it would be some List interface method then there will be ClassCastException on execution.如果它是某个 List 接口方法,那么执行时会出现 ClassCastException。 Let us say size().让我们说 size()。

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

If you create a generic class instance without generic parameters the compiler gives a warning and does not control usage of the created instance any more.如果您创建一个没有泛型参数的泛型类实例,编译器会发出警告并且不再控制所创建实例的使用。 As to why the code works without declaring generic type - because in this case T is assumed to be Object, that is any type is good至于为什么代码在没有声明泛型类型的情况下工作 - 因为在这种情况下,T 被假定为 Object,任何类型都是好的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM