首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java:将类型转换为泛型

Java:将类型转换为泛型
EN

Stack Overflow用户
提问于 2010-05-12 04:02:36
回答 3查看 4.6K关注 0票数 2

这个方法使用方法级的泛型,它解析来自自定义POJO,JXlistOfKeyValuePairs的值(确切地说就是这样)。唯一的问题是,JXlistOfKeyValuePairs中的键和值都是String的。

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

这是我得到的代码,很明显它被破坏了。

代码语言:javascript
复制
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;
}

这就是我想要解决的问题:

代码语言:javascript
复制
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。

有什么建议吗?

示例方法调用:

代码语言:javascript
复制
Map<String, Boolean> foo = fromListOfKeyValuePairs(bar, Boolean.class);

解决了,感谢“克里斯多兰”和“多基因洗脱剂”。其原因是,当与原始人的自动装箱相结合时,类型被混淆了。之所以避免编译器警告,是因为方法参数clasz的类型是Class<T>,而不仅仅是ClassClass<?>,因此调用cast方法是类型错误。

使劲。索伦:

代码语言:javascript
复制
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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-05-12 04:25:26

您可以使用Class<T>.cast方法,而不是自己执行未经检查的(T)强制转换。

代码语言:javascript
复制
    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));
    }

没有编译器警告。

至于为什么原始代码不编译,这是因为您试图将原始直接转换为未知的引用类型。直接将从原语转换为引用类型只能在非常特定的情况下工作,在所有这些情况下,必须在编译时知道该类型。

代码语言:javascript
复制
    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

下面是一个参数化类型泛型示例:这有点傻,但是将原语直接转换为一个未知的引用类型的问题重新说明如下:

代码语言:javascript
复制
<T> T f() {
    //return (T) 42; // DOESN'T COMPILE!!!
    return (T) (Integer) 42; // compiles with warning about unchecked cast
}

参考文献

  • Java语言指南/自动装箱
  • JLS 5.1.7拳击转换
  • JLS 5.1.8取消装箱转换
  • JLS 5.1.5扩大基准转换
票数 5
EN

Stack Overflow用户

发布于 2010-05-12 04:21:01

这是你想要的

代码语言:javascript
复制
    if (clasz.isAssignableFrom(Boolean.class))
    {
        value = (T)Boolean.valueOf(Boolean.parseBoolean(str));
    } else if (clasz.isAssignableFrom(Integer.class))
    {
        value = (T)Integer.valueOf(Integer.parseInt(str));
    } else if (clasz.isAssignableFrom(Float.class))
    {
        value = (T)Float.valueOf(Float.parseFloat(str));
    }

问题是您的代码愚弄了自动装箱,所以编译器不会自动将原始boolean转换为Boolean实例。我把明显的转换和瞧。代码抱怨未检查的强制转换,但这是不可避免的,所以您需要@SuppressWarnings

票数 2
EN

Stack Overflow用户

发布于 2010-05-12 04:20:40

最简单的解决方案可能只是将事物,特别是值变量和映射作为对象,然后在方法返回时将其转换为(T)。

你会收到一堆未经检查的警告,但无论如何你都会得到的.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2816053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档