问题描述
新的Java程序员经常对编译错误消息感到困惑,例如:
New Java programmers are often confused by compilation error messages like:
这行代码:
int squareRoot = Math.sqrt(i);
这个错误意味着什么,你如何解决?
What does this error mean, and how do you fix it?
推荐答案
首先,这是一个编译错误。如果您在运行时在异常消息中看到它,那是因为您运行了编译错误的程序。
First of all, this is a compilation error. If you ever see it in an exception message at runtime, it is because you have have run a program with compilation errors.
一般消息的形式是这样的:
The general form of the message is this:
其中 < type1>
和 < type2>
都是原始数字类型;即 byte
, char
, short
, int
, long
, float
或 double
。
where <type1>
and <type2>
are both primitive numeric types; i.e. one of byte
, char
, short
, int
, long
, float
or double
.
当您的代码尝试从 <$ c $进行隐式转换时,会发生此错误c>< type1> 到 < type2>
但转换可能是有损。
This error happens when your code attempts to do an implicit conversion from <type1>
to <type2>
but the conversion could be lossy.
在问题的示例中:
int squareRoot = Math.sqrt(i);
sqrt
方法产生 double
,但是从 double
到 int
的转换可能是有损的。
the sqrt
method produces a double
, but a conversion from double
to int
is potentially lossy.
好吧,看看几个例子。
-
将
long
转换为int
是一种潜在的有损转换,因为long
值没有相应的int
值。例如,大于2 ^ 31 - 1的任何long
值太大而无法表示为int
。同样,任何小于-2 ^ 31的数字都太小。
A conversion of a
long
to anint
is a potentially lossy conversion because there arelong
values that do not have a correspondingint
value. For example, anylong
value that is greater than 2^31 - 1 is too large to be represented as anint
. Similarly, any number less than -2^31 is too small.
转换 int
到 long
不是有损转换,因为每个 int
值都有一个相应的 long
value。
A conversion of an int
to a long
is NOT lossy conversion because every int
value has a corresponding long
value.
将 float
转换为 long
是一个潜在的有损转换,因为 float
值太大或太小而无法表示为 long
值。
A conversion of a float
to an long
is a potentially lossy conversion because there float
values that are too large or too small to represent as long
values.
将 long
转换为 float
不是有损转换,因为每个 long
值都有一个相应的 float
值。 (转换后的值可能不太精确,但损失并不意味着......在这种情况下。)
A conversion of an long
to a float
is NOT lossy conversion because every long
value has a corresponding float
value. (The converted value may be less precise, but "lossiness" doesn't mean that ... in this context.)
这些都是可能有损的转换:
These are all the conversions that are potentially lossy:
-
short
tobyte
或char
-
char
到字节
或短
-
int
tobyte
,short
或char
-
long
tobyte
,短
,char
或int
-
float
至byte
,short
,char
,int
或long
-
double
tobyte
,short
,char
,int
,long
或float
。
short
tobyte
orchar
char
tobyte
orshort
int
tobyte
,short
orchar
long
tobyte
,short
,char
orint
float
tobyte
,short
,char
,int
orlong
double
tobyte
,short
,char
,int
,long
orfloat
.
使编译错误消失的方法是添加类型转换。例如;
The way to make the compilation error go away is to add a typecast. For example;
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
的值。 (转换将截断,而不是舍入。)
But is that really a fix? Consider that the square root of 47
is 6.8556546004
... but squareRoot
will get the value 6
. (The conversion will truncate, not round.)
那么这个怎么样?
byte b = (int) 512;
这导致 b
获取值 0
。通过屏蔽高阶位来完成从较大的int类型转换为较小的int类型,并且 512
的低阶8位全部为零。
That results in b
getting the value 0
. Converting from a larger int type to a smaller int type is done by masking out the high order bits, and the low-order 8 bits of 512
are all zero.
简而言之,您不应该简单地添加类型转换,因为它可能无法为您的应用程序执行正确的 。
In short, you should not simply add a typecast, because it might not do the correct thing for your application.
相反,您需要了解代码需要进行转换的原因:
Instead, you need to understand why your code needs to do a conversion:
- 是否发生这种情况是因为您在代码中犯了其他错误?
-
< type1>
是一个不同的类型,所以这里不需要有损转换? - 如果需要进行转换,那么无声有损转换是类型转换会做正确的行为吗?
- 或者您的代码是否应该进行一些范围检查并通过抛出异常处理错误/意外值?
- Is this happening because you have made some other mistake in your code?
- Should the
<type1>
be a different type, so that a lossy conversion isn't needed here? - If a conversion is necessary, is the silent lossy conversion that the typecast will do the correct behavior?
- Or should your code be doing some range checks and dealing with incorrect / unexpected values by throwing an exception?
订阅时可能出现有损转换。
"Possible lossy conversion" when subscripting.
第一个例子:
for (double d = 0; d < 10.0; d += 1.0) {
System.out.println(array[d]); // <<-- possible lossy conversion
}
这里的问题是数组索引值必须是 int
。所以 d
必须从 double
转换为 int
。通常,使用浮点值作为索引没有意义。有人认为Java数组的工作方式与(比如)Python字典相似,或者他们忽略了浮点运算通常不精确的事实。
The problem here is that array index value must be int
. So d
has to be converted from double
to int
. In general, using a floating point value as an index doesn't make sense. Either someone is under the impression that Java arrays work like (say) Python dictionaries, or they have overlooked the fact that floating-point arithmetic is often inexact.
解决方案是重写代码以避免使用浮点值作为数组索引。 (添加类型转换可能是一个不正确的解决方案。)
The solution is to rewrite the code to avoid using a floating point value as an array index. (Adding a type cast is probably an incorrect solution.)
第二个例子:
for (long l = 0; l < 10; l++) {
System.out.println(array[l]); // <<-- possible lossy conversion
}
这是一个变种上一个问题,解决方案是一样的。不同之处在于根本原因是Java数组仅限于32位索引。如果你想要一个数组类似数据结构,它有超过2个 - 1个元素,你需要定义或找到一个类来完成它。
This is a variation of the previous problem, and the solution is the same. The difference is that the root cause is that Java arrays are limited to 32 bit indexes. If you want an "array like" data structure which has more than 2 - 1 elements, you need to define or find a class to do it.
这篇关于什么是“可能的有损转换”?是什么意思,我该如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!