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

Java 什么是;“可能的有损转换”;我的意思是,我如何修复它?,java,compiler-errors,Java,Compiler Errors,新的Java程序员经常被编译错误消息弄糊涂,例如: “不兼容类型:可能从double转换为int” 对于这一行代码: int squareRoot = Math.sqrt(i); 一般来说,“可能的有损转换”错误消息是什么意思?如何修复它?首先,这是一个编译错误。如果您在运行时在异常消息中看到它,那是因为您运行的程序存在编译错误1 信息的一般形式如下: “不兼容类型:从到的可能有损转换” 其中和都是基本数字类型;i、 e.byte、char、short、int、long、float或doubl

新的Java程序员经常被编译错误消息弄糊涂,例如:

“不兼容类型:可能从double转换为int”

对于这一行代码:

int squareRoot = Math.sqrt(i);

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

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

信息的一般形式如下:

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

其中
都是基本数字类型;i、 e.
byte
char
short
int
long
float
double
中的一种

当代码尝试从
进行隐式转换时,会发生此错误,但转换可能有损

在问题中的示例中:

  int squareRoot = Math.sqrt(i);
sqrt
方法产生一个
double
,但是从
double
int
的转换可能有损

“潜在损耗”是什么意思? 让我们来看几个例子

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

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

  • float
    转换为
    long
    可能是一种有损转换,因为
    float
    值太大或太小,无法表示为
    long

  • long
    转换为
    float
    不是有损转换,因为每个
    long
    值都有相应的
    float
    值。(转换后的值可能不太精确,但“丢失”并不意味着……在这种情况下。)

  • 以下是所有可能有损的转换:

    • short
      byte
      char
    • char
      byte
      short
    • int
      byte
      short
      char
    • long
      byte
      short
      char
      int
    • float
      byte
      short
      char
      int
      long
    • double
      to
      byte
      short
      char
      int
      long
      float
    如何修复错误? 消除编译错误的方法是添加类型转换。比如,

      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;
    
    这将导致
    b
    获取值
    0
    。从较大的int类型转换为较小的int类型是通过屏蔽掉高阶位来完成的,而
    512
    的低阶8位都是零

    简而言之,您不应该简单地添加类型转换,因为它可能不适合您的应用程序

    相反,您需要理解为什么代码需要进行转换:

    • 发生这种情况是因为您在代码中犯了其他错误吗
    • 是否应该是另一种类型,以便此处不需要有损转换
    • 如果有必要进行转换,则无提示有损转换是否意味着typecast将执行正确的行为
    • 或者您的代码是否应该执行一些范围检查,并通过抛出异常来处理不正确/意外的值
    订阅时的“可能有损转换”。 第一个例子:

    for (double d = 0; d < 10.0; d += 1.0) {
        System.out.println(array[d]);  // <<-- 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);
        }
    }
    
    int a = 21;
    byte b1 = a;   // <<-- possible lossy conversion
    byte b2 = 21;  // OK
    
    使用Java 11编译上述内容可以得到以下结果:

    $ 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 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);
        }
    }
    
    int a = 21;
    byte b1 = a;   // <<-- possible lossy conversion
    byte b2 = 21;  // OK
    
    给出一个编译错误



    1-例如,EclipseIDE有一个选项,允许您忽略编译错误并运行代码。如果选择此选项,IDE的编译器将创建一个
    .class
    文件,在该文件中,出现错误的方法将在调用时引发未检查的异常。异常消息将提到编译错误消息。

    对于更有用的“特定情况”有什么建议吗?我正在寻找一些例子,其中根本原因是对Java语言的一些明显的误解。。。这还没有涵盖。您没有提到的一个用例是数组初始化。例如,
    int[]a={23L}
    长l=23;int[]a={l}