Ste*_*n C 7 java compiler-errors
新的Java程序员经常对编译错误消息感到困惑,例如:
"不兼容的类型:从double到int的可能有损转换"
对于这行代码:
int squareRoot = Math.sqrt(i);
Run Code Online (Sandbox Code Playgroud)
这个错误意味着什么,你如何解决它?
Ste*_*n C 17
首先,这是一个编译错误.如果你在运行时在异常消息中看到它,那是因为你运行了一个带有编译错误的程序1.
消息的一般形式是:
"不兼容的类型:可能有损转换
<type1>为<type2>"
where <type1>和<type2>都是原始数字类型; 的即,一个byte,char,short,int,long,float或double.
当你的代码试图做一个发生这种错误的隐式从转换<type1>到<type2>但转换可能是有损耗的.
在问题中的示例中:
int squareRoot = Math.sqrt(i);
Run Code Online (Sandbox Code Playgroud)
该sqrt方法产生double,而是从一个转换double到int具有潜在的损耗.
那么让我们看看几个例子.
的A转换long到一个int是一个潜在的有损转换,因为有long不具有一个相应的值int的值.例如,任何long大于2 ^ 31 - 1的值都太大而无法表示为int.同样,任何小于-2 ^ 31的数字都太小.
a int到a的long转换不是有损转换,因为每个int值都有相应的long值.
的A转换float到一个long是一个潜在的有损转换,因为有float值过大或过小,无法表示为long数值.
a long到a的float转换不是有损转换,因为每个long值都有相应的float值.(转换后的值可能不太精确,但"损失"并不意味着......在这种情况下.)
这些都是可能有损的转换:
short到byte或charchar到byte或shortint到byte,short或charlong到byte,short,char或intfloat对byte,short,char,int或者longdouble对byte,short,char,int,long或float.使编译错误消失的方法是添加类型转换.例如;
int i = 47;
int squareRoot = Math.sqrt(i); // compilation error!
Run Code Online (Sandbox Code Playgroud)
变
int i = 47;
int squareRoot = (int) Math.sqrt(i); // no compilation error
Run Code Online (Sandbox Code Playgroud)
但这真的是一个解决方案吗?考虑平方根47是6.8556546004......但squareRoot会得到值6.(转换将截断,而不是舍入.)
那怎么样?
byte b = (int) 512;
Run Code Online (Sandbox Code Playgroud)
这导致b获得价值0.通过掩蔽高阶位来完成从较大的int类型到较小的int类型的转换,并且低阶8位512全部为零.
简而言之,您不应该简单地添加类型转换,因为它可能无法为您的应用程序执行正确的操作.
相反,您需要了解代码需要进行转换的原因:
<type1>是不同的类型,这样就不需要有损转换吗?下标时"可能有损转换".
第一个例子:
for (double d = 0; d < 10.0; d += 1.0) {
System.out.println(array[d]); // <<-- possible lossy conversion
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是数组索引值必须是int.所以d必须转换double为int.通常,使用浮点值作为索引是没有意义的.有人认为Java数组的工作方式与(比如)Python字典相似,或者他们忽略了浮点运算通常不精确的事实.
解决方案是重写代码以避免将浮点值用作数组索引.(添加类型转换可能是一个不正确的解决方案.)
第二个例子:
for (long l = 0; l < 10; l++) {
System.out.println(array[l]); // <<-- possible lossy conversion
}
Run Code Online (Sandbox Code Playgroud)
这是前一个问题的变体,解决方案是相同的.不同之处在于根本原因是Java数组仅限于32位索引.如果你想要一个"数组类似"的数据结构,它有超过2 31 1个元素,你需要定义或找到一个类来完成它.
1 - 例如,Eclipse IDE有一个选项,允许您忽略编译错误并运行代码.如果选择此选项,IDE的编译器将创建一个21文件,其中带有错误的方法将在调用时抛出未经检查的异常.异常消息将提及编译错误消息.