简体   繁体   中英

If Java String extends Object then why cant it be passed to <? extends Object> type

For example why doesn't the following work?

Map<String, ? extends Object> table = new HashMap<>();
table.put("K", "V"); //Error V cannot be applied to ? extends String.

However String must extend Object, why does the above throw compiler error?

The IntelliJ error I get is

Wrong 2nd Argument Type. Found 'java.lang.String'required: '? extends java.lang.Object'

However the following works:

Map<String, ? super Object> table = new HashMap<>();
table.put("K", "V"); //Error V cannot be applied to ? extends String.

Now the above is truly weird. How can a lowerbound work on Object class?

I mean doesn't

? super Object

mean an "Unknown that is superclass of Object"?

AFAIK Object is at root of Java class hierarchy.

Because ? extends Object ? extends Object does not mean "any type that extends Object." It means "some specific type, which we don't know what it is, as long as it extends Object." The difference is subtle, but significant!

The following code compiles totally fine:

Map<String, Integer> stringToInteger = new HashMap<>();
Map<String, ? extends Object> stringToWildcard = stringToInteger;

It makes sense that that would compile. stringToWildcard is a map whose value is "some type ... as long as it extends Object" -- and Integer is a type that extends object.

So, given that, imagine if your table.put("K", "V") worked. We could do this:

Map<String, Integer> stringToInteger = new HashMap<>();

Map<String, ? extends Object> stringToWildcard = stringToInteger;
stringToWildcard.put("K", "V");

Integer value = stringToInteger.get("K");

This would result in a ClassCastException on the last line, since the string "V" can't be cast to an Integer.

Instead, the compiler will disallow table.put("K", "V") . What it's telling you is: "hey, the value needs to be some specific type. I don't know what that type is, other than that it extends Object. But I can't let you put a String in, because I don't know if that type is String."

This item solved my question:

How can I add to List<? extends Number> data structures?

The only problem I have in the above explanation is for a construct of form

List<? super T> myList;

the post goes on to say you can add any type T to myList or any of T's Supertype instance . That does not seem accurate. It looks like you can only add a T or any of its subtypes since a subtype of T is automatically subtype of any of T's supertypes. So a little ambiguity there.

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