为什么String&amp ;;整数不是Object的超类?
List<? super Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // no compile error
mylist.add(2);
我知道wild card guidelines使用较低的有界外卡和超出'out'变量,但在这种情况下,似乎Object不起'下界'的作用。
这也是允许在列表中添加任何类型的唯一方法吗?
答案 0 :(得分:4)
这很简单。请记住,在Java中,子类型的实例也是其超类型的实例。
查看add
public boolean add(E e)
这意味着无论您传递的是类型为E
的内容还是E
的任何子类型。
你有List<? super Object>
。因此,您可以传递myList.add()
类型为? super Object
(可能是Object
或其超类型的未知类型)或其任何子类型的任何内容。
整数是? super Object
包含的所有类型的子类型吗?当然。 Integer
是Object
的子类型,它是? super Object
包含的所有类型的子类型(当然,在这种情况下,只有Object
满足此要求。)
您将type参数与可以传递给方法的内容混淆。 List<? super Object>
的类型参数是未知类型,是Object
的超类型,因此Integer
或String
不能是实际的类型参数。实际上,在这种情况下,唯一有效的实际类型参数是Object
。但是当你传递一些东西给你的方法时,你问的是,我正在传递一个子类型吗?答案是肯定的。
答案 1 :(得分:3)
这是因为Object是Integer和String的超类。你正在以相反的方式解释泛型关系。
修改强>
想想这种情况:
List<? extends myClass> listOfMyClass = new ArrayList<Object>();
在这种情况下,您最终会得到Object
类型元素的列表,但必须遵守listOfMyClass
列表声明所添加的限制。
您将能够将属于myClass
层次结构的任何对象添加到列表中。实现ArrayList
接口的List
将在请求时保留(并返回)Object
个类型元素。
当然,您可以定义:
List<? extends myClass> listOfMyClass = new ArrayList<mySuperClass>();
正如您现在所做的那样,ArrayList
必须包含具有相同类型或超类型myClass
的对象,在这种情况下,这是mySuperClass
。此列表将返回qhen请求的mySuperClass
个对象。
将ClassX
作为不属于mySuperClass层次结构的类,以下行将无法编译:
List<? extends myClass> listOfMyClass = new ArrayList<ClassX>();
那是因为ClassX
不是myClass
的超类。
答案 2 :(得分:3)
我同意这令人困惑,但这就是正在发生的事情。
在这行代码中:
List<? super Object> mylist...
您说myList
是List
,其中每个元素的类型可以是Object
,也可以是超级类Object
。但是,您只是在这里声明myList
的类型。
通配符的作用限制了myList
的实现。
然后,你这样做:
List<? super Object> mylist = new ArrayList<Object>();
现在您正在做的是实例化ArrayList<Object>
。您的下限通配符用于检查这是否有效。它有效,因为Object
匹配? super Object
。此时,您有一个List<Object>
,并允许您随后的方法调用。