首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >“有损转换的可能性”是什么意思,我该如何解决?

“有损转换的可能性”是什么意思,我该如何解决?
EN

Stack Overflow用户
提问于 2019-06-14 00:13:11
回答 1查看 0关注 0票数 0

新的Java程序员经常对编译错误消息感到困惑,例如:

“不兼容的类型:从double到int的可能有损转换”

对于这行代码:

代码语言:javascript
复制
int squareRoot = Math.sqrt(i);

这个错误意味着什么,你如何解决它?

EN

回答 1

Stack Overflow用户

发布于 2019-06-14 09:38:39

首先,这是一个编译错误。如果你在运行时在异常消息中看到它,那是因为你运行了一个带有编译错误的程序1。

消息的一般形式是:

“不兼容的类型:可能有损转换<type1><type2>

where <type1><type2>都是原始数字类型; 的即,一个bytecharshortintlongfloatdouble

当你的代码试图做一个发生这种错误的隐式从转换<type1><type2>但转换可能是有损耗的

在问题中的示例中:

代码语言:javascript
复制
  int squareRoot = Math.sqrt(i);

sqrt方法产生double,而是从一个转换doubleint具有潜在的损耗。

“潜在有损”是什么意思?

那么让我们看看几个例子。

  1. 的A转换long到一个int是一个潜在的有损转换,因为有long不具有一个相应的值int的值。例如,任何long大于2 ^ 31 - 1的值都太大而无法表示为int。同样,任何小于-2 ^ 31的数字都太小。
  2. a int到a的long转换不是有损转换,因为每个int值都有相应的long值。
  3. 的A转换float到一个long是一个潜在的有损转换,因为有float值过大或过小,无法表示为long数值。
  4. a long到a的float转换不是有损转换,因为每个long值都有相应的float值。(转换后的值可能不太精确,但“损失”并不意味着......在这种情况下。)

这些都是可能有损的转换:

  • shortbytechar
  • charbyteshort
  • intbyteshortchar
  • longbyteshortcharint
  • floatbyteshortcharint或者long
  • doublebyteshortcharintlongfloat

你如何解决这个错误?

使编译错误消失的方法是添加类型转换。例如;

代码语言:javascript
复制
  int i = 47;
  int squareRoot = Math.sqrt(i);         // compilation error!

代码语言:javascript
复制
  int i = 47;
  int squareRoot = (int) Math.sqrt(i);   // no compilation error

但这真的是一个解决方案吗?考虑平方根476.8556546004......但squareRoot会得到值6。(转换将截断,而不是舍入。)

那怎么样?

代码语言:javascript
复制
  byte b = (int) 512;

这导致b获得价值0。通过掩蔽高阶位来完成从较大的int类型到较小的int类型的转换,并且低阶8位512全部为零。

简而言之,您不应该简单地添加类型转换,因为它可能无法为您的应用程序执行正确的操作。

相反,您需要了解代码需要进行转换的原因:

  • 这是因为您在代码中犯了其他错误吗?
  • 应该<type1>是不同的类型,这样就不需要有损转换吗?
  • 如果转换是必要的,那么类型转换会做出正确行为的静默有损转换吗?
  • 或者您的代码是否应该进行一些范围检查并通过抛出异常来处理错误/意外值?

一些具体案例:

下标时“可能有损转换”。

第一个例子:

代码语言:javascript
复制
for (double d = 0; d < 10.0; d += 1.0) {
    System.out.println(array[d]);  // <<-- possible lossy conversion
}

这里的问题是数组索引值必须是int。所以d必须转换doubleint。通常,使用浮点值作为索引是没有意义的。有人认为Java数组的工作方式与(比如)Python字典相似,或者他们忽略了浮点运算通常不精确的事实。

解决方案是重写代码以避免将浮点值用作数组索引。(添加类型转换可能是一个不正确的解决方案。)

第二个例子:

代码语言:javascript
复制
for (long l = 0; l < 10; l++) {
    System.out.println(array[l]);  // <<-- possible lossy conversion
}

这是前一个问题的变体,解决方案是相同的。不同之处在于根本原因是Java数组仅限于32位索引。如果你想要一个“数组类似”的数据结构,它有超过2 31 1个元素,你需要定义或找到一个类来完成它。

1 - 例如,Eclipse IDE有一个选项,允许您忽略编译错误并运行代码。如果选择此选项,IDE的编译器将创建一个.class文件,其中带有错误的方法将在调用时抛出未经检查的异常。异常消息将提及编译错误消息。

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

https://stackoverflow.com/questions/-100005193

复制
相关文章

相似问题

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