新的Java编程人员经常因编译错误信息感到困惑,例如:
"incompatible types: possible lossy conversion from double to int"
对于这行代码:
int squareRoot = Math.sqrt(i);
一般来说,“可能有损转换”错误消息是什么意思,如何修复它?
新的Java编程人员经常因编译错误信息感到困惑,例如:
"incompatible types: possible lossy conversion from double to int"
对于这行代码:
int squareRoot = Math.sqrt(i);
一般来说,“可能有损转换”错误消息是什么意思,如何修复它?
int squareRoot = Math.sqrt(i);
sqrt
方法返回一个double
类型的值,但是从double
类型转换为int
类型可能会有损失。
让我们来看几个例子。
将一个`long`转换为`int`是一种潜在的有损转换,因为存在一些`long`值没有对应的`int`值。例如,任何大于2^31 - 1的`long`值都太大无法表示为`int`。同样,任何小于-2^31的数值也太小。 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;
0
。将较大的int类型转换为较小的int类型是通过屏蔽高位比特并将512
的低8位全部置零来完成的。<type1>
应该是不同的类型,这样就不需要进行损失转换吗?
- 如果需要进行转换,类型转换所执行的“静默”损失转换是否是正确的行为?
- 或者你的代码应该进行四舍五入而不是截断,或者通过抛出异常来处理不正确/意外的值?
for (double d = 0; d < 10.0; d += 1.0) {
System.out.println(array[d]); // <<-- possible lossy conversion
}
for (long l = 0; l < 10; l++) {
System.out.println(array[l]); // <<-- possible lossy conversion
}
public class User {
String name;
short age;
int height;
public User(String name, short age, int height) {
this.name = name;
this.age = age;
this.height = height;
}
public static void main(String[] args) {
User user1 = new User("Dan", 20, 190);
}
}
$ javac -Xdiags:verbose User.java
User.java:20: error: constructor User in class User cannot be applied to given types;
User user1 = new User("Dan", 20, 190);
^
required: String,short,int
found: String,int,int
reason: argument mismatch; possible lossy conversion from int to short
1 error
20
是一个int
类型,而构造函数中对应的参数声明为short
类型。将int
转换为short
会有信息丢失。
示例:
public int compute() {
long result = 42L;
return result; // <<-- possible lossy conversion
}
return
可以被看作是对返回值的“赋值”。但无论你如何思考,都需要将提供的值转换为方法的实际返回类型。可能的解决方案是添加一个类型转换(表示“我承认有损失”)或者改变方法的返回类型。
考虑以下情况:
byte b1 = 0x01;
byte mask = 0x0f;
byte result = b1 & mask; // <<-- possible lossy conversion
byte result = (byte) (b1 & mask);
int a = 21;
byte b1 = a; // <<-- possible lossy conversion
byte b2 = 21; // OK
21
是一个类型为int
的数值字面量。(没有byte
或short
字面量。)因此,在这两种情况下,我们都将一个int
赋值给一个byte
。int
值都能放入一个byte
中。21
是一个始终能放入byte
中的值。byte
、char
或short
:
byte
、short
、char
或int
。请注意,这仅适用于赋值语句,或者更准确地说,在赋值上下文中。因此:
Byte b4 = new Byte(21); // incorrect
BigDecimal .valueOf (Math .sqrt(2)) .intValueExact ()
和 .intValue ()
。如果参数应该是整数,请使用 intValueExact
。如果截断对您来说可以接受或者它可以被证明是一个整数(如 Math .sqrt (Math .multiplyExact (i, i))
),则使用后者。在后一种情况下,您可能希望 assert r * r == i
(r
代表您的 squareRoot
)。.charValueExact
。
int[] a = {23L};
或long l = 23; int[] a = {l};
- Lino