具有可选多边界的泛型,例如List <?extends Integer OR String>

Som*_*omu 0 java generics unbounded-wildcard

我有一个方法应该只接受Map其键的类型String和类型的值,Integer 或者 String,但不是,例如,Boolean.

例如,

map.put("prop1", 1); // allowed
map.put("prop2", "value"); // allowed
map.put("prop3", true); // compile time error
Run Code Online (Sandbox Code Playgroud)

无法在下面声明Map(以强制执行编译时检查).

void setProperties(Map<String, ? extends Integer || String> properties)
Run Code Online (Sandbox Code Playgroud)

什么是最好的替代比声明值类型为其他unbounded wildcard和验证的IntegerString在运行时?

void setProperties(Map<String, ?> properties)
Run Code Online (Sandbox Code Playgroud)

此方法接受一组属性以配置基础服务实体.实体支持类型StringInteger单独的属性值.例如,属性maxLength=2有效,defaultTimezone=UTC也有效,但allowDuplicate=false无效.

小智 5

另一个解决方案是自定义Map实现和覆盖验证数据的方法putputAll方法:

public class ValidatedMap extends HashMap<String, Object> {
    @Override
    public Object put(final String key, final Object value) {
        validate(value);
        return super.put(key, value);
    }

    @Override
    public void putAll(final Map<? extends String, ?> m) {
        m.values().forEach(v -> validate(v));
        super.putAll(m);
    }

    private void validate(final Object value) {
        if (value instanceof String || value instanceof Integer) {
            // OK
        } else {
            // TODO: use some custom exception
            throw new RuntimeException("Illegal value type");
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:使用Map适合您需求的实现作为基类

  • 它可以简单地增强:没有**需要硬编码所示的允许类型.你可以简单地传递一个允许类型的`List <Class>; 然后使用class.isAssignableFrom()来检查传入的值.当然,必须记住,每次和任何添加都会进行此验证. (2认同)