Java无法从盒装类型转换为基本类型

时间:2015-05-13 15:12:06

标签: java

我正在尝试使用Class.cast()将盒装Double转换为原始double:

Object d = 1.0d;
Class<?> clazz = double.class;
//the bellow line throws java.lang.ClassCastException: 
//Cannot cast java.lang.Double to double
clazz.cast(d);

我这样做是因为在我的代码的某些部分,动态地给出了一个值对象和一个类,并且我确保值对象是兼容类型。但是这个例外让我很困惑。使用cast()的合同是什么?

更新我遇到了这个,因为我们的代码如下:

interface Provider <T> {
  T get ();
  Class<T> getClazz();
}

//a special handling for double primitive
class DoubleProvider implements Provider<Double> {

  public double getDouble(){
      return 1.0d;
  }

  @Override
  public Double get() {
    return getDouble();
  }

  @Override
  public Class<Double> getClazz() {
    //why this actually compiles?
    return double.class;
  }
}

如果double和Double是如此不同以至于它们都不被认为是可分配的,为什么java允许DoubleProvider中的getClazz()方法进行编译? double.class和Double.class之间的关系是什么?

2 个答案:

答案 0 :(得分:6)

你不能 Doubledouble(反之亦然),因为它们都不是另一个的子类型。使用(double)代替自动取消装箱值。

  

使用cast()的合同是什么?

API的javadoc是方法的契约。在这种情况下javadoc says

  

将对象强制转换为此Class对象所代表的类或接口。

     

[...]

     

<强>抛出:     ClassCastException - 如果对象不为null且不能分配给类型T。

如果您需要根据Class获取Object的原始(未装箱)版本,我认为没有比

更好的方法了。
if (clazz == double.class)
    handleDouble((double) o);
if (clazz == int.class)
    handleInt((int) o);
...

关于您的修改:这是因为double.class的类型为Class<Double>JLS states

  

p.class的类型,其中p是基本类型的名称(第4.2节),是Class<B>,其中B是表达式的类型在拳击转换后输入p(§5.1.7)。

答案 1 :(得分:3)

Auto [un] boxing本质上是一个编译技巧。它的明确目的是隐瞒原语是可分配或可转换为相应的包装类类型,而反之亦然。每当您认为自己将double分配给Double类型的变量时(例如),您实际上首先在double中自动装箱Double然后分配,好像你写过这样的东西:

Double wrapper = Double.valueOf(1.0d);

在当天,我们必须手动完成。

  

我这样做是因为在我的代码的某些部分,动态地给出了一个值对象和一个类

如果您确实收到了值对象,则不应出现问题。基元不是对象,Java无法处理 bona fide 基元,它应该允许您将它与对象混淆。如果您有一个接受Object引用的方法,或者如果您有一个包含一个的变量,那么您可以100%确信引用的对象不是double或任何其他原语,尽管它可以是Double或其他一个包装类的实例。

<强>更新 如果您的系统需要处理基本类型的值以及包装器类型的值,保持它们之间的区别,那么您可能需要为基元提供一个特殊情况。您可以通过Class.isPrimitive()标识表示基元的类。其中正好有九个,包括Void.TYPE

<强> UPDATE2: 在回答添加的问题时,Double.TYPE的类型(原始的,仍然有效,double.class的拼写)为Class<Double>。因此,它是具有该返回类型的方法的有效返回值。 &#34;为何&#34?;问题总是有点棘手,但我认为推断Double.TYPE具有特定类参数的至少一个原因是没有任何更好的选择,这是公平的。类型参数必须是引用类型的名称。 double不是引用类型,因此double.class的类型不能是Class<double>Class<Double>是次佳选择。

请注意:虽然Double.classdouble.class都有类型 java.lang.Class<java.lang.Double>,但它们是不同的类。