简体   繁体   中英

Can the Object class really be a lower bound?

Why is the following legal when String & Integer are not super classes of Object ?

List<? super Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // no compile error
mylist.add(2);

I'm aware that wild card guidelines use lower bounded wild cards and super for 'out' variables but it seems that Object doesn't function as a 'lower bound' in this case.

Also is this the only way to allow addition of any type into a list ?

It's really simple. Remember that in Java, an instance of a subtype is also an instance of its supertypes.

Look at the signature of add

public boolean add(E e)

That means whatever you pass something whose type is E or any subtype of E .

You have a List<? super Object> List<? super Object> . So you can pass to myList.add() anything whose type is ? super Object ? super Object (an unknown type which could be Object or supertype thereof) or any subtype thereof.

Is Integer a subtype of all types contained by ? super Object ? super Object ? Of course. Integer is a subtype of Object , which is a subtype of all types contained by ? super Object ? super Object (of course, in this case, only Object satisfies this).

You're confusing the type parameter with the things you can pass to methods. The type argument of List<? super Object> List<? super Object> is an unknown type that is a supertype of Object , so Integer or String cannot be the actual type parameter. In fact, in this case the only valid actual type argument would be Object . But what you're asking when you pass something to the method is, is the thing I'm passing a subtype? And the answer is yes.

It's because Object is a superclass for Integer and String. You're interpreting the generic relationship the other way around.

Edit

Think about this situation:

List<? extends myClass> listOfMyClass = new ArrayList<Object>();

In this case, you'll end up with a list of Object type elements but that have to respect the restriction added by the declaration of the listOfMyClass list.

You'll be able to add any object that belongs to the myClass hierarchy to the list. The ArrayList that's implementing the List interface will hold (and return) Object type elements when requested.

Of course, you can define this:

List<? extends myClass> listOfMyClass = new ArrayList<mySuperClass>(); 

As you might now, the ArrayList must contain objects with the same type or a supertype of myClass and, in this case, that's the mySuperClass . This list will return mySuperClass objects qhen requested.

Taking ClassX as a class that does not belong to the mySuperClass hierarchy, the following line won't compile:

List<? extends myClass> listOfMyClass = new ArrayList<ClassX>(); 

That's because ClassX is not a superclass of myClass .

I agree that it's confusing, but here's what's happening.

In this line of code:

List<? super Object> mylist...

You're saying that myList is a List , where each element can be of a type that is Object or a superclass of Object . However, you're only declaring the type of myList here.

What the wildcard does is restricts your implementation of myList .

Then, you do this:

List<? super Object> mylist = new ArrayList<Object>();

Now what you're doing is instantiating an ArrayList<Object> . Your lower bound wildcard is used to check that this is valid. It is valid, because Object matches ? super Object ? super Object . At this point, you have a List<Object> and your ensuing method calls are permitted.

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