Sridhar
Sridhar

Reputation: 2532

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 ?

Upvotes: 4

Views: 175

Answers (3)

newacct
newacct

Reputation: 122519

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>. So you can pass to myList.add() anything whose type is ? 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? Of course. Integer is a subtype of Object, which is a subtype of all types contained by ? 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> 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.

Upvotes: 4

Fritz
Fritz

Reputation: 10055

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.

Upvotes: 3

Dancrumb
Dancrumb

Reputation: 27579

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. At this point, you have a List<Object> and your ensuing method calls are permitted.

Upvotes: 3

Related Questions