创建字符串和函数的映射,它采用参数化类型

时间:2015-07-24 02:40:36

标签: generics java-8

我想创建一个(键,函数)的映射,以便我可以获得一个特定键的正确功能,其中'key'是字符串。该函数采用(键,值)的映射,两者都是字符串,返回ExtractedParam类型的结果。

这是ExtractedParam类

class ExtractedParams<T> {
String key;
Optional<T> value;
String errorMessage;

public ExtractedParams(String key, Optional<T> value, String message) {
    this.key = key;
    this.value = value;
    this.errorMessage = message;
}

public Optional<T> getValue() { return  value;}
}

这是具有主要方法和功能的类

public class Spike {
private static Function< Map<String,String>, ExtractedParams<String> > typeExtractor = (m) -> {
    if (!m.containsKey("type")) {
        return new ExtractedParams<>("type", Optional.empty(), "type is a mandatory parameter");
    }
    String dt = m.get("type");
    return new ExtractedParams<>("type", Optional.of(dt), null);
};

private static Function< Map<String,String>, ExtractedParams<Integer> > valueExtractor = (m) -> {
    if (!m.containsKey("v")) {
        return new ExtractedParams<>("v", Optional.empty(), "v is a mandatory parameter");
    }
    Integer v = 0;
    try {
        v = Integer.parseInt(m.get("v"));
    }
    catch (NumberFormatException e) {
        return new ExtractedParams<>("v", Optional.<Integer>empty(), "v is a number");
    }
    return new ExtractedParams<>("v", Optional.of(v), null);
};

private static Map<String, Function<Map<String, String>, ExtractedParams<? extends Object> > > paramFunctionMapper = new HashMap();

public static void main(String[] args) {

    paramFunctionMapper.put("type", typeExtractor);   // compiler error
    paramFunctionMapper.put("value", valueExtractor); // compiler error                                                                               }
}

}

正如您所看到的,我正在尝试为哈希映射的键添加特定函数。但是编译器将其标记为错误,表示'put'方法的第二个参数不是',ExtractedParams',而是',ExtractedParams'(在第一次放置的情况下)

我一直以为ExtractedParams应该允许ExtractedParams或ExtractedParams。

这里有什么问题?请帮我理解。

(UPDATE)使用上面的ExtractParams类编译

public static void main(String[] args) {
    Map< String, ExtractedParams<? extends Object>> map = new HashMap<>();
    map.put("type",new ExtractedParams<String>("dt", Optional.of("number"), ""));
    map.put("value",new ExtractedParams<Integer>("value", Optional.of(4), ""));

}

1 个答案:

答案 0 :(得分:3)

虽然E<String>E<? extends Object>的子类,但F<E<String>>不是F<E<? extends Object>>的子类。

正如您必须E<? extends Object>使其成为E<String>的超级类,所以您必须F<? extends E<? extends Object>>

如果您将地图声明为Map<String, Function<Map<String, String>, ? extends ExtractedParams<? extends Object>>>,则会进行编译。

或者,您可以使用通配符声明函数:

private static Function< Map<String, String>, ExtractedParams<?>> valueExtractor = ....

而且,最可读的方法可能是将提取器声明为方法,然后使用方法引用:

static ExtractedParams<String> getType(Map<String, String> m) {
     .....
}

Map<String, Function<Map<String, String>, ExtractedParams<?>>> mapper = new HashMap<>();

mapper.put("type", Spike::getType);