当前位置: 首页 > 知识库问答 >
问题:

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

易博文
2023-03-14
int squareRoot = Math.sqrt(i);

一般来说,“可能的有损转换”错误消息是什么意思,您如何修复它?

共有1个答案

郑翰海
2023-03-14

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

消息的一般形式如下:

“不兼容的类型:从 的转换可能有损”

  int squareRoot = Math.sqrt(i);

让我们来看几个例子。

>

  • long转换为int可能是有损的转换,因为有些long值没有相应的int值。例如,任何long大于2^31-1的值都太大,不能表示为int。同样,任何小于-2^31的数字都太小。

    int转换为long不是有损转换,因为每个int值都有相应的long值。

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

    • 字节字符
    • charbyteshort
    • int字节字符
    • 字节字符int
    • 浮动字节字符int
    • 字节字符int浮点.

    消除编译错误的方法是添加一个typecast。例如;

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

    那这个呢?

      byte b = (int) 512;
    

    这将导致b获得值0。从较大的int类型转换为较小的int类型是通过屏蔽高阶位来完成的,512的低阶8位都为零。

    简而言之,您不应该简单地添加一个类型转换,因为它可能不会为您的应用程序做正确的事情。

      null
    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
    }
    

    这是前一个问题的变体,解决方案是一样的。不同之处在于根本原因是Java数组被限制为32位索引。如果您想要一个包含超过231-1个元素的“像数组一样”的数据结构,您需要定义或找到一个类来完成它。

    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
    
    int a = 21;
    byte b1 = a;   // <<-- possible lossy conversion
    byte b2 = 21;  // OK
    

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

    首先,JLS声明21是一个数值文本,其类型为int。(没有字节文本。)因此,在这两种情况下,我们都将int赋值给byte

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

    • 该值是编译时常量表达式(包括文本)的结果。
    • 表达式的类型是byteshortcharint
    • 所赋的常量值在“target”类型的域中是可表示的(没有丢失)。

    请注意,这只适用于赋值语句,或者更严格地说,适用于赋值上下文。因此:

    Byte b4 = new Byte(21);  // incorrect
    

    给出编译错误。

  •  类似资料: