bgu*_*uiz 2 java generics casting class
这种方法使用方法级泛型,它解析自定义POJO中的值JXlistOfKeyValuePairs(正是这样).唯一的问题是键和值JXlistOfKeyValuePairs都是Strings.
除了JXlistOfKeyValuePairs实例之外,此方法还需要Class<T>定义将值转换为哪种数据类型(假设只有Boolean,Integer并且Float可能).然后HashMap,它为其条目中的值输出具有指定类型的a .
这是我得到的代码,它显然已被破坏.
private <T extends Object> Map<String, T>
fromListOfKeyValuePairs(JXlistOfKeyValuePairs jxval, Class<T> clasz)
{
Map<String, T> val = new HashMap<String, T>();
List<Entry> jxents = jxval.getEntry();
T value;
String str;
for (Entry jxent : jxents)
{
str = jxent.getValue();
value = null;
if (clasz.isAssignableFrom(Boolean.class))
{
value = (T)(Boolean.parseBoolean(str));
} else if (clasz.isAssignableFrom(Integer.class))
{
value = (T)(Integer.parseInt(str));
} else if (clasz.isAssignableFrom(Float.class))
{
value = (T)(Float.parseFloat(str));
}
else {
logger.warn("Unsupported value type encountered in key-value pairs, continuing anyway: " +
clasz.getName());
}
val.put(jxent.getKey(), value);
}
return val;
}
Run Code Online (Sandbox Code Playgroud)
这是我要解决的问题:
if (clasz.isAssignableFrom(Boolean.class))
{
value = (T)(Boolean.parseBoolean(str));
} else if (clasz.isAssignableFrom(Integer.class))
{
value = (T)(Integer.parseInt(str));
}
Run Code Online (Sandbox Code Playgroud)
我明白了: Inconvertible types required: T found: Boolean
此外,如果可能的话,我希望能够使用更优雅的代码执行此操作,避免使用Class#isAssignableFrom.
有什么建议?
示例方法调用:
Map<String, Boolean> foo = fromListOfKeyValuePairs(bar, Boolean.class);
Run Code Online (Sandbox Code Playgroud)
解决了,感谢@Chris Dolan和@polygenelubricants.原因是当与原语的自动装箱结合时,类型转换变得混乱.避免编译器警告,因为方法参数clasz属于类型Class<T>,而不仅仅是Class或者Class<?>,因此调用cast方法是类型安全的.
IMPL.溶液:
private <T extends Object> Map<String, T> fromListOfKeyValuePairs(
JXlistOfKeyValuePairs jxval, Class<T> clasz)
{
Map<String, T> val = new HashMap<String, T>();
List<Entry> jxents = jxval.getEntry();
T value;
String str;
for (Entry jxent : jxents)
{
str = jxent.getValue();
value = null;
if (clasz.isAssignableFrom(Boolean.class))
{
value = clasz.cast(Boolean.parseBoolean(str));
}
else if (clasz.isAssignableFrom(Integer.class))
{
value = clasz.cast(Integer.valueOf(Integer.parseInt(str)));
}
else if (clasz.isAssignableFrom(Float.class))
{
value = clasz.cast((Object)Float.parseFloat(str));
}
else
{
logger.warn("Unsupporteded value type encountered in key-value pairs, continuing anyway: " +
clasz.getName());
}
val.put(jxent.getKey(), value);
}
return val;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用该Class<T>.cast方法而不是执行自己的未经检查的强制转换(T).
if (clasz.isAssignableFrom(Boolean.class)) {
value = clasz.cast(Boolean.parseBoolean(str));
} else if (clasz.isAssignableFrom(Integer.class)) {
value = clasz.cast(Integer.parseInteger(str));
} else if (clasz.isAssignableFrom(Float.class)) {
value = clasz.cast(Float.parseFloat(str));
}
Run Code Online (Sandbox Code Playgroud)
没有编译器警告.
至于为什么原始代码不能编译,这是因为你试图直接将原语转换为未知的引用类型.铸造直接从原始社会到引用类型只能在非常特殊的情况,而在所有这些情况下,类型必须知道在编译时.
Object o;
o = (Integer) 42; // works! Boxing conversion!
o = (Number) 42; // works! Autoboxing then widening reference conversion!
o = (Object) 42; // works! Autoboxing then widening reference conversion!
o = 42; // YES! This also compiles!!!
o = (String) ((Object) 42); // compiles fine!
// will throw ClassCastException at run-time
o = (String) 42; // DOESN'T COMPILE!!!
Run Code Online (Sandbox Code Playgroud)
最后一行类似于从基元直接转换为未知参数化类型T(即(T) Integer.parseInt(s)),这就是它不能编译的原因.确实,你正在尝试编写T适当类型的代码,但是在编译时无法确认,因为T通常可以是任何类型.
在它已经转换为引用类型之后,通过间接转换原语String,前一行到最后一行会绕过编译时错误Object.这就是它编译的原因,当然它会ClassCastException在运行时抛出.
这是一个参数化类型的通用示例:它有点愚蠢,但重新演示了将基元直接转换为未知引用类型的问题:
<T> T f() {
//return (T) 42; // DOESN'T COMPILE!!!
return (T) (Integer) 42; // compiles with warning about unchecked cast
}
Run Code Online (Sandbox Code Playgroud)