“可能的有损转换”是什么意思,我该如何解决?
新的Java程序员经常会被编译错误消息搞糊涂,例如:
“不兼容的类型:从double到int的可能有损转换”
对于这行代码:
int squareRoot = Math.sqrt(i);
这个错误意味着什么,你如何解决它?
首先,这是一个编译错误。 如果你在运行时在exception消息中看到它,那是因为你已经运行了一个带有编译错误的程序1 。
消息的一般forms是:
“不兼容的类型:从
到
可能有损转换”
其中
和
都是原始数字类型; 即byte
, char
, short
, int
, long
, float
或double
。
当您的代码尝试从
到
进行隐式转换但转换可能有损时会发生此错误。
在问题中的示例中:
int squareRoot = Math.sqrt(i);
sqrt
方法产生一个double
,但是从double
到int
的转换可能是有损的。
“潜在有损”是什么意思?
那么让我们看看几个例子。
-
将
long
转换为int
是一种潜在的有损转换,因为有一些long
值没有相应的int
值。 例如,任何大于2 ^ 31 – 1的long
值都太大而无法表示为int
。 同样,任何小于-2 ^ 31的数字都太小。 -
将
int
转换为long
不是有损转换,因为每个int
值都具有相应的long
值。 -
将
float
转换为long
是一种潜在的有损转换,因为float
值太大或太小而不能表示为long
值。 -
将
long
转换为float
不是有损转换,因为每个long
值都有相应的float
值。 (转换后的值可能不太精确,但“损失”并不意味着……在这种情况下。)
这些都是可能有损的转换:
-
short
到byte
或char
-
char
到byte
或short
-
int
到byte
,short
或char
-
long
tobyte
,short
,char
或int
-
float
tobyte
,short
,char
,int
或long
-
double
tobyte
,short
,char
,int
,long
或float
。
你如何解决这个错误?
使编译错误消失的方法是添加类型转换。 例如;
int i = 47; int squareRoot = Math.sqrt(i); // compilation error!
变
int i = 47; int squareRoot = (int) Math.sqrt(i); // no compilation error
但这真的是一个解决方案吗? 考虑到47
平方根是6.8556546004
…但squareRoot
将得到值6
。 (转换将截断,而不是舍入。)
那怎么样?
byte b = (int) 512;
这导致b
得到值0
。 通过屏蔽高阶位来完成从较大的int类型转换为较小的int类型,并且512
的低阶8位全部为零。
简而言之,您不应该简单地添加类型转换,因为它可能无法为您的应用程序执行正确的操作。
相反,您需要了解代码需要进行转换的原因:
- 这是因为您在代码中犯了其他错误吗?
-
应该是不同的类型,这样就不需要有损转换吗? - 如果转换是必要的,那么类型转换会做出正确行为的静默有损转换吗?
- 或者您的代码是否应该进行一些范围检查并通过抛出exception来处理错误/意外值?
一些具体案例:
下标时“可能有损转换”。
第一个例子:
for (double d = 0; d < 10.0; d += 1.0) { System.out.println(array[d]); // <<-- possible lossy conversion }
这里的问题是数组索引值必须是int
。 所以d
必须从double
转换为int
。 通常,使用浮点值作为索引没有意义。 有人认为Java数组的工作方式与(比如)Python字典相似,或者他们忽略了浮点运算通常不精确的事实。
解决方案是重写代码以避免使用浮点值作为数组索引。 (添加类型转换可能是一个不正确的解决方案。)
第二个例子:
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
文件,其中带有错误的方法将在调用时抛出未经检查的exception。 exception消息将提及编译错误消息。
- 在非单例bean上修复Spring代理上的BeanNotOfRequiredTypeException?
- Java:如何将一个hashmap插入MongoDB?
- Maven无法执行目标org.codehaus.mojo:exec-maven-plugin:1.3
- wait.until(ExpectedConditions.visibilityOf Element1 OR Element2)
- GWT中共享包的重要性
- 我该如何渲染2D手电筒效果?
- Java:排序集合允许重复,具有内存效率并提供快速插入和更新
- 如何使用VK_UP或VK_DOWN移动到上一个或下一个Textfield?
- Spring Batch:从一个带有新线程的Spring MVC控制器中启动一个作业