为了账号安全,请及时绑定邮箱和手机立即绑定

“可能的有损转换”意味着什么?我如何修复它?

“可能的有损转换”意味着什么?我如何修复它?

qq_花开花谢_0 2019-07-03 10:28:11
“可能的有损转换”意味着什么?我如何修复它?新的Java程序员常常对编译错误消息感到困惑,例如:“不兼容类型:可能从双重到int的有损转换”对于这一行代码:int squareRoot = Math.sqrt(i);一般来说,“可能的有损转换”错误消息意味着什么,以及如何修复它?
查看完整描述

2 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

首先,这是一个编译错误。如果您在运行时在异常消息中看到它,这是因为您运行了一个程序,其中包含编译错误。1.

该信息的一般形式如下:

“不兼容类型:可能从<type1><type2>"

哪里<type1><type2>都是原始数字类型;即bytecharshortintlongfloatdouble.

当您的代码尝试执行隐式转换自<type1><type2>但转换可能是洛西.

在问题的例子中:

  int squareRoot = Math.sqrt(i);

这个sqrt方法生成一个double,但是从doubleint可能会有损失。

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

好吧,让我们来看看几个例子。

  1. a转换为along转到int是潜在的有损转换,因为long值,这些值没有对应的int价值。例如,任何long大于2^31-1的值太大,不能将其表示为int..同样,任何小于-2^31的数字都太小了。

  2. 转换int转到long不是有损转换,因为int值具有相应的long价值。

  3. a转换为afloat转到long是潜在的有损转换,因为float值太大或太小,不能表示为long价值。

  4. 转换long转到float不是有损转换,因为long值具有相应的float价值。(转换值可能不太精确,但“价值”并不意味着.在这方面)

这些都是潜在有损失的转换:

  • short

    byte

    char

  • char

    byte

    short

  • int

    byteshort

    char

  • long

    byteshortchar

    int

  • float

    byteshortcharint

    long

  • double

    byteshortcharintlong

    float.

如何纠正错误?

使编译错误消失的方法是添加一个类型广播。例如;

  int i = 47;
  int squareRoot = Math.sqrt(i);         // compilation error!

  int i = 47;
  int squareRoot = (int) Math.sqrt(i);   // no compilation error

但这真的是个解决办法吗?的平方根476.8556546004..但squareRoot会得到价值6..(转换将截断,而不是圆形。)

那这个呢?

  byte b = (int) 512;

这会导致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}

这里的问题是数组索引值必须是int..所以d必须从doubleint..通常,使用浮点值作为索引是没有意义的。要么有人认为Java数组像Python字典那样工作,要么他们忽略了浮点运算通常是不精确的事实。

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

第二个例子:

for (long l = 0; l < 10; l++) {
    System.out.println(array[l]);  // <<-- possible lossy conversion}

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

带有文字的“可能的有损转换”

考虑到这一点:

INT a=21;字节b1=a;/<-可能的有损转换字节b2=21;/OK

怎么一回事?为什么一个版本是允许的,而另一个版本是不允许的?(毕竟他们“做”了同样的事情!)

首先,JLS声明:21是类型为int..(没有byteshort(文字)因此,在这两种情况下,我们都要分配一个int转到byte.

在第一种情况下,错误的原因是并非所有int值将适合于byte.

在第二种情况下,编译器知道21是一个始终适合于byte.

技术上的解释是赋值上下文,则允许执行*基元收缩转换。to a字节,焦耳or矮的if:  - the value is the result of a compile time *constant expression* (which includes literals), and  - the type of the expression is字节,矮的,焦耳or和-该值在“目标”类型中是可表示的(不丢失的)。

请注意,这仅适用于赋值语句。因此:

字节b4=新字节(21);/不正确

提供编译错误,尽管编译器不会将其描述为“可能的有损转换”。(它会说没有匹配的构造函数。)


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


查看完整回答
反对 回复 2019-07-03
?
SMILET

TA贡献1796条经验 获得超4个赞

对于更有用的“具体案例”,有什么建议吗?我正在寻找一些例子,其中的根本原因是对Java语言的一些明显的误解.这还没有包括在内。

查看完整回答
反对 回复 2019-07-03
  • 2 回答
  • 0 关注
  • 507 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号