【问题标题】:Cannot cast java.lang.Float to float when using Class.cast?使用 Class.cast 时无法将 java.lang.Float 转换为浮动?
【发布时间】:2011-09-22 21:25:44
【问题描述】:

我已经有了解决方案,但我不喜欢它。另外,很高兴知道您对此的看法。

你看,elem.get 会返回一个Object,在 x 和 y 的情况下,这将是一个 Float

这段代码抛出了标题中描述的异常:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);
        arg.add(types[i].cast(elem.get(names[i])));
    }
}

代码用于定义实例化对象的参数列表。参数和对象的类名都在一个外部数据文件中定义(但没关系)。

解决方案,我不喜欢的东西(因为它失去了我试图获得的灵活性),在 for:

if(types[i] == float.class)
{
    float v = (Float)elem.get(names[i]);
    arg.add(v);
} else
{
    arg.add(types[i].cast(elem.get(names[i])));
    break;
}

其他选项是将types 中的float.class 更改为Float.class,但我不会这样做,因为该代码用于实例化在其构造函数中具有float 参数的对象。

谢谢!

【问题讨论】:

  • 如果您使用的是 java 1.5 或更高版本,浮点数将自动拆箱为浮点数,不是吗?您是否尝试过使用 Float.class?
  • 正如我所写,我不想使用 Float.class,因为我需要在之后的实例化中将参数用作浮点数。但是如果我在这段代码中使用 Float.class,它就可以工作。它只是稍后在尝试实例化构造函数具有浮点数的 Object 时失败。感谢您的回答!

标签: java class casting


【解决方案1】:

由于args 的类型是ArrayList&lt;Object&gt;,所以无论如何您都不能避免拳击:

// This code...
float v = (Float)elem.get(names[i]);
arg.add(v);

// Will actually be equivalent to:
float v = (Float)elem.get(names[i]);
Float boxed = v;
arg.add(boxed);

如果重点是通过反射调用构造函数,那么您将必须为任何float 参数传递Float - 这就是它的工作原理。 p>

所以基本上,将float.class 更改为Float.class,它应该可以正常工作。编辑:啊,除非par 列表类型错误。基本上你想cast Float.class,但是add float.class 到参数类型列表中。

您可能想要一个从原始类型到包装器类型的映射,如下所示:

private static final Map<Class<?>>, Class<?>> PRIMITIVE_TYPE_MAP =
    buildPrimitiveTypeMap();

private static Map<Class<?>>, Class<?>> buildPrimitiveTypeMap()
{
    Map<Class<?>>, Class<?>> map = new HashMap<Class<?>>, Class<?>>();
    map.put(float.class, Float.class);
    map.put(double.class, Double.class);
    // etc
    return map;
}

然后:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);

        // For primitive types, only box to the wrapper type
        Class<?> castType = PRIMITIVE_TYPE_MAP.get(types[i]);
        if (castType == null)
        {
            castType = types[i];
        }
        arg.add(castType.cast(elem.get(names[i])));
    }
}

事实上,如果你相信这些值已经是正确的类型,我怀疑你可以这样做:

arg.add(elem.get(names[i]));

毕竟,您只是转换为特定类型,然后再次丢失该类型信息...使用cast 调用确实会检查执行时类型是否正确,因此您可能想要出于这个原因保留它。

【讨论】:

  • 糟糕。对不起。 arg 是一个 ArrayList.
  • @huff:是的,正如我所想的那样——当你向它添加float 时,它无论如何都会被装箱到Float。将编辑我的答案以使其更清楚。
  • 谢谢!所以,但是当我使用 Float.class 时,它没有找到合适的构造函数来实例化对象。
  • @huff:已编辑。有点尴尬 - 如果 Class 有一个 getWrapperClass 方法为非原始类型返回 null 那就太好了:( 如果你可以信任原始数据,你当然不需要做演员,这避免了这个问题:)
  • @huff:你应该走另一条路:给定float.class(“正确”参数类型),你想保留参数类型的信息,但转到强制转换的包装器类型称呼。否则,任何真正具有Float 参数的构造函数都会出现问题。
猜你喜欢
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 2015-12-10
  • 2016-04-14
  • 1970-01-01
  • 2020-12-27
相关资源
最近更新 更多