简体   繁体   中英

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. The method test expects (T y) where T extends Date and implements List , but it works with gt.test(new Date()) .

When you instantiate like this:

GenericTest gt = new GenericTest() 

you use the raw version of GenericTest type. This means that T type will be replaced with it's first bound (in your case, Date ). That's why the method contract of GenericTest#test() has a Date parameter, but not a List one.

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. If it would be some List interface method then there will be ClassCastException on execution. Let us say 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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