Understanding upper and lower bounds on ? in Java Generics

后端 未结 6 501
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-29 01:45

I am really having a tough time understanding the wild card parameter. I have a few questions regarding that.

  1. ? as a type parameter can only

6条回答
  •  甜味超标
    2020-11-29 02:15

    ? as a type parameter can only be used in methods. eg: printAll(MyList) I cannot define classes with ? as type parameter.

    A wildcard (?) isn't a formal type parameter, but rather can be used as a type argument. In the example you give, ? extends Serializable is given as a type argument to the generic type MyList, of the printAll method's parameter.

    Methods can also declare type parameters like classes, for example:

    static  void printAll(MyList myList)
    

    I understand the upper bound on ?. printAll(MyList) means printAll will print MyList if it has objects that implement the Serialzable interface

    More accurately, it means a call to printAll will compile only if it is passed a MyList with some generic type that is or implements Serializable. In this case it would accept a MyList, MyList, etc.

    I have a bit of an issue with the super. printAll(MyList) means printAll will print MyList if it has objects of MyClass or any class which extends MyClass (the descendants of MyClass)

    A wildcard bounded with super is a lower bound. So we could say a call to printAll will compile only if it is passed a MyList with some generic type that is MyClass or some super-type of MyClass. So in this case it would accept MyList, e.g. MyList, or MyList.

    So, say if MyClass looks like:

    public class MyClass extends Thread implements ActionListener{
        // whatever
    }
    

    then, printAll() will print if

    1. There are objects of MyClass in the list
    2. There are objects of Thread or ActionListener in the list

    You're on the right track. But I think saying e.g. "it will print if there are objects of MyClass in the list" is problematic. That makes it sound like you're defining runtime behavior - generics are all about compile time checks. For example wouldn't be able to pass a MyList as an argument for MyList, even though it might contain instances of MyClass, by inheritance. I would reword it to:

    A call to printAll(MyList) will compile only if it is passed a:

    1. MyList
    2. MyList
    3. MyList
    4. MyList
    5. MyList
    6. MyList
    7. MyList where X is MyClass, Thread, Runnable, ActionListener, EventListener, or Object.
    8. So, after having read the many answers to the question, here is my understanding:

      ? extends T means any class which extends T. Thus, we are referring to the children of T. Hence, T is the upper bound. The upper-most class in the inheritance hierarchy

      ? super T means any class / interface which is super of T. Thus we are referring to all the parents of T. T is thus the lower bound. The lower-most class in the inheritance hierarchy

      Close, but I wouldn't say "children of T" or "parents of T", since these bounds are inclusive - it would be more accurate to say "T or its subtypes", and "T or its supertypes".

      提交回复
      热议问题