我正在尝试使用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之间的关系是什么?
答案 0 :(得分:6)
你不能 Double
到double
(反之亦然),因为它们都不是另一个的子类型。使用(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.class
和double.class
都有类型 java.lang.Class<java.lang.Double>
,但它们是不同的类。