Help Java generics: cannot use “object” as parameter “? Extends object“

I have the following code:

import java.util.*;

public class SellTransaction extends Transaction {
    private Map<String,? extends Object> origValueMap;
    public SellTransaction(Map<String,? extends Object> valueMap) {
        super(Transaction.Type.Sell);
        assignValues(valueMap);
        this.origValueMap=valueMap;
    }
    public SellTransaction[] splitTransaction(double splitAtQuantity) {
        Map<String,? extends Object> valueMapPart1=origValueMap;
        valueMapPart1.put(nameMappings[3],(Object)new Double(splitAtQuantity));
        Map<String,? extends Object> valueMapPart2=origValueMap;
        valueMapPart2.put(nameMappings[3],((Double)origValueMap.get(nameMappings[3]))-splitAtQuantity);
        return new SellTransaction[] {new SellTransaction(valueMapPart1),new SellTransaction(valueMapPart2)};
    }
}

When I call valuemappart1 Put and valuemappart2 When put, the code cannot be compiled with the following error:

The method put(String,capture#5-of ? extends Object) in the type Map is not applicable for the arguments (String,Object)

I've read about generics and wildcards and capture on the Internet, but I still don't understand what's wrong My understanding is that the value of map can be any class that extends object. I think this may be redundant because all classes extend object I can't change generics to something like that? Super object, because map is provided by some libraries

Then why not compile? In addition, if I try to convert valuemap to map < string, Object >, the compiler will give me an "unchecked conversion" warning

thank you!

Solution

If libraries specify extensions, they explicitly prohibit placement You should make defensive copies before modifying, because they can reasonably change their return type to immutable in the new version If copying is expensive, you can try to create a mapping type of < string, Object > First query their maps, and then query the maps you created with local modifications

If you do know that their return type is immutable and you only have it, the @ suppresswarnings ("unchecked") comment is a legitimate way to resolve warnings, but I will carefully examine these assumptions and make extensive comments

To learn about extensions vs super, view it this way Since this value can be any type of extended object, the following is valid

Map<String,Number> strToNum = new HashMap<String,Number>();
strToNum.put("one",Integer.valueOf(1));  // OK

Map<String,String> strToStr = new HashMap<String,String>();
strToStr.put("one","1");  // OK

Map<String,? extends Object> strToUnk = randomBoolean() ? strToNum : strToStr;
strToUnk.put("null",null);  // OK.  null is an instance of every reference type.
strToUnk.put("two",Integer.valueOf(2));  // NOT OK.  strToUnk might be a string to string map
strToUnk.put("two","2");  // NOT OK.  strToUnk might be a string to number map

So put does not apply to extended boundary types But it can work well with reading operations such as get:

Object value = strToUnk.get("one");  // We don't kNow whether value is Integer or String,but it is an object (or null).

If you want the map to use "put" instead of "get", you can use "super" instead of extend, as shown below:

Map<String,Number>();
Map<String,Object> strToObj = new HashMap<String,Object>();

Map<String,? super Number> strToNumBase;
if (randomBoolean()) {
  strToNumBase = strToNum;
} else {
  strToNumBase = strToObj;
}

// OK.  We kNow that any subclass of Number can be used as values.
strToNumBase.put("two",Double.valueOf(2.0d));

// But Now,gets don't work as well.
Number n = strToNumBase.get("one");  // NOT OK.
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>