我非常了解泛型,但遇到了一个我不太明白的看似简单的问题。看一下下面的例子。
public <T extends Object> T getSetting(String settingName) {
return settings.getJsonObject(settingName).getValue("value");
}
settings
是类型vertx.core.json.JsonObject
的实例属性。 getValue
的结果是Object
。
我认为将返回类型设置为T
我可以返回任何Object
类型或超级类型String
或Integer
。但是,此代码给出了以下错误消息。
不兼容的类型:
java.lang.Object
无法转换为T
我在这里俯瞰什么?
答案 0 :(得分:1)
该代码无法编译,因为无论T是在编译时决定的,都不需要匹配将在运行时确定的getValue
返回的内容
这根本不受限制。
您可以添加(T)
强制转换,这会在警告中转换错误,但这不会阻止潜在的运行时强制转换错误,这就是为什么它会保留为警告。
我认为没有任何真正的解决方法,因为你永远无法确定getValue
返回的类型......但是你可以提供一些方法,至少会:
一个。更优雅地失败(有更好的错误信息),
湾如果类型不是预期的类型,则返回默认值
℃。让用户有机会提供转换lambda转换 任何可能的输入类型到预期的返回值类中。
E.g。
public <T> T getSetting(String settingName, Class<T> clazz) {
final Object obj = settings.getJsonObject(settingName).getValue("value");
if (obj == null)
return null;
else if (!clazz.isInstance(obj))
throw new IllegalArgumentException(String.format("wrong setting class; was expecting %s but found %s", clazz.getSimpleName(), obj.getClass().getName());
else {
@SuppressWarnings("unchecked")
T casted = (T) obj; // this way you don't suppress unchecked warning in other parts of this method.
return casted;
}
}
...
Integer x = getSetting("mysetting", Integer.class);
或者:
public <T> T getSetting(String settingName, Function<Object, T> cast) {
final Object obj = settings.getJsonObject(settingName).getValue("value");
return obj == null ? null : cast.apply(obj);
}
...
Integer x = getSetting("mysetting", o -> Integer.parseInt(o.toString()));