Java:类型转换为泛型

标签 java generics class casting

此方法使用方法级泛型,解析来自自定义 POJO 的值 JXlistOfKeyValuePairs (正是如此)。唯一的事情是 JXlistOfKeyValuePairs 中的键和值是String s。

这个方法想要采纳,除了JXlistOfKeyValuePairs例如,一个Class<T>定义将值转换为哪种数据类型(假设只有 BooleanIntegerFloat 是可能的)。然后它输出 HashMap为其条目中的值指定类型。

这是我得到的代码,它显然已损坏。

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;
}

这是我想要解决的问题:

if (clasz.isAssignableFrom(Boolean.class))
{
    value = (T)(Boolean.parseBoolean(str));
} else if (clasz.isAssignableFrom(Integer.class))
{
    value = (T)(Integer.parseInt(str));
}

我得到:Inconvertible types required: T found: Boolean

另外,如果可能的话,我希望能够使用更优雅的代码来做到这一点,避免使用 Class#isAssignableFrom。

有什么建议吗?

<小时/>

方法调用示例:

Map<String, Boolean> foo = fromListOfKeyValuePairs(bar, Boolean.class);
<小时/>

解决了,感谢@Chris Dolan 和@polygenelubricants。原因是当与基元的自动装箱结合时,类型转换变得困惑。避免了编译器警告,因为方法参数 clasz类型为Class<T> ,而不仅仅是 ClassClass<?> ,因此调用 cast方法是类型安全的。

实现。解决方案:

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;
}

最佳答案

您可以使用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));
    }

没有编译器警告。

<小时/>

至于为什么原始代码无法编译,这是因为您试图将原始代码直接转换为未知的引用类型。从原始类型直接转换为引用类型仅适用于非常特定的情况,并且在所有这些情况下,类型必须在编译时已知

    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!!!

最后一行类似于从基元直接转换为未知参数化类型 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
}

引用文献

关于Java:类型转换为泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2816053/

相关文章:

java - 从 Java 应用程序控制批处理文件的进程

java - ArrayList书籍类

c++ - 这个模板函数对类型有什么要求

java - 为什么不显示此 Swing 选项卡式 Pane ?

C++ move 复制构造函数和 move 赋值运算符

java - xText 2 - 处理 token

java - 丢失数据,Map 包含字符串和整数

java - 如何创建通用原始数组?

java - ExecutorService 未经检查的分配

java - 无法找到或加载主类、环境变量