提问人:Vince 提问时间:10/14/2023 最后编辑:Vince 更新时间:10/19/2023 访问量:184
Integer -> double unbox,但 Double -> int 不拆箱。为什么?
Integer -> double unboxes, but Double -> int doesn't unbox. Why?
问:
为避免混淆,我正在寻找规则/JLS 条目。
我不是在问为什么会失败,我是在问它失败的方式
Double -> int
正如我在问题中提到的,我知道有损转换 - 我不是在问数据丢失
double -> int
我不是在问某人为什么开发人员以这种方式设计它的“最佳猜测”
我问为什么执行转换(拆箱和加宽),而不执行转换(甚至不拆箱)Integer -> double
Double -> int
我正在寻找提到这种转换不一致的 JLS 条目,其中取消装箱发生在一种情况下,而不是另一种情况下。Reference -> primitive
此转换编译时没有错误Integer -> double
double d = Integer.valueOf(1);
这意味着会发生以下情况:
Integer
已取消装箱int
- 该值经历了从
int
int -> double
Integer
已拆箱。然后,将扩大未装箱的值。这给出了与int -> double
创建的假设也将拆箱,其行为与Double -> int
double -> int
对于代码
int i = Double.valueOf(1);
我期待错误消息
从 double 到 int 的有损转换
假设 gets unboxed,我们应该观察到与Double
double -> int
相反,我们得到一个输入错误
无法将 Double 转换为 int
这种行为背后的解释是什么?
为什么 之间发生拆箱,但 之间没有拆箱?Integer -> double
Double -> int
为什么这些是一致的:
Integer -> double
int -> double
但这些不是:
Double -> int
double -> int
答:
Double
只有两种方法:一种用于字符串
输入,一种用于双精度
输入。valueOf
因此,当您写下这显然是 ,方法签名是这样的(如果它甚至要运行),您的值将升级为 a,然后方法运行。因此,Java 编译器真的会说 your 是“double不能安全地转换为int,所以:不”。Double.valueOf(1)
1
int
valueOf(double)
int
double
int i = Double.valueOf(1)
int i = Double.valueOf(1.0)
当然,它甚至不需要这样做:它知道 的返回值是 ,无论你输入了什么,所以它看到试图将 Double 分配给 int 的代码,知道这是不可能的,并且不关心其他任何事情,它会说“RHS 与 LHS 不兼容,所以:不”。Double.valueOf
Double
有趣的是,“The[sic] create the assumpsion[sic] that Double -> int
will also unbox”既是错误的(没有值的拆箱发生),也不是完全错误的(有“unboxing”类型)。你给Java一个带有类型的赋值,Java看到不兼容的类型,但也知道这是一个原始赋值,可以拆箱到基元。然而,由于这仍然是一个不兼容的赋值,Java 会忽略原始的 int/Double 不兼容错误(这样你就知道“你的代码出了什么问题”,而不是“解析器应用的任何代码魔术中出了什么问题”)int = Double
Double
double
评论
Double.valueOf(1)
int
Double.valueOf(...)
"...这给出了与
int -> double
...“ 相同的行为
这就是转换。Integer 对象被取消装箱为 int。
从来没有一个整数可以加倍。
"...假设
Double
被拆箱,我们应该观察到与double -> int
相同的行为......”
我完全不期望 Java 这样做。
而且,不幸的是,我没有指标。
我想,如果该值不能在单个操作中取消装箱和赋值,编译器就会失败。
为避免混淆,我正在寻找规则/JLS 条目。
- 我不是在问为什么 Double -> int 会失败,我是在问它失败的方式
你要求的东西不存在。
Java 语言规范通常不强制要求编译错误的措辞。特别是,Java 语言规范的相关部分仅描述了赋值上下文中允许哪些隐式转换,但没有列举不允许的转换组合,更不用说在每种情况下应该给出哪个错误消息(或者如果几种情况适用,如何选择消息)。
所有规范的要求是编译器拒绝无效的转换,消息的措辞取决于编译器实现者,不同的编译器实际上发出不同的消息。
例如,如果您要求 Eclipse Compiler for Java 进行编译
int i = Math.PI;
int j = Double.valueOf(Math.PI);
它说:
Type mismatch: cannot convert from double to int
Type mismatch: cannot convert from Double to int
评论
Object obj = 5;
下表显示了 §5.5 中允许的转换:
- 表示不允许转换
- ω 表示扩大基元转换
- ⊗表示拆箱转换
该表显示了执行取消装箱和扩大转换,但不执行取消装箱。Integer -> double
Double -> int
由于不会发生拆箱,因此我们得到的是类型错误,而不是有损转换错误。
评论
(int) Double.valueOf(1)
int i = Double.valueOf(1)
评论
Integer -> double
Double -> int
int)(double)
来做。(int)