Подтвердить что ты не робот

Что вызывает эту ошибку "возможной потери точности"?

У меня проблема с моей конечной переменной. Любая помощь будет принята с благодарностью.

Это мой первый код, который отлично работает

final int i = 90; 
byte b = i ; 
System.out.println(i);

Вот мой второй код, в котором говорится возможная потеря точности. Что здесь не так?

final int i; 
i = 90;
byte b = i ; 
System.out.println(i);
4b9b3361

Ответ 1

Я не смог найти точную причину этого в JLS, поэтому я прошел через байтовый код и обнаружил, что причина в том, что компилятор не смог встроить значение i в второй случай, но в состоянии сделать это в первом случае.

Здесь код:

final int x = 90;
System.out.println(x);

final int i;
i = 90;
System.out.println(i);

Скомпилированный байт-код выглядит так:

 0: getstatic     #2        // Field java/lang/System.out:Ljava/io/PrintStream;
 3: bipush        90
 5: invokevirtual #3        // Method java/io/PrintStream.println:(I)V
 8: bipush        90
10: istore_2
11: getstatic     #2        // Field java/lang/System.out:Ljava/io/PrintStream;
14: iload_2
15: invokevirtual #3        // Method java/io/PrintStream.println:(I)V
18: return

Итак, в первом случае (от 3 до 5) он использует значение 90 для печати, а во втором случае (от 8 до 15) он должен сохранить значение в переменной, а затем загрузить обратно на стек. Затем метод print будет выбирать верхнее значение стека.

Итак, в случае назначения:

byte x = i;

Значение i будет выбрано из стека во время выполнения и не будет включено в компилятор. Поэтому компилятор не знает, какое значение может иметь значение i.

Конечно, это все мое предположение. Байт-код может отличаться для разных JVM. Но у меня есть сильная интуиция, что это может быть причиной.

Кроме того, JLS & sect; 4.12.4 может иметь значение здесь:

Переменная примитивного типа или типа String, которая является окончательной и инициализирована выражением константы времени компиляции (§15.28), называется постоянной переменной.

Так как во втором случае переменная не инициализируется константным выражением, но позже ей присваивается значение, она больше не является постоянной переменной.

Ответ 2

Просто первый способ, которым компилятор "знает", что 90 может вписываться в байтовую переменную, но во втором, он не может определить значение "i" и не знает, какое значение он может содержать, а потому не уверен, что он может вписываться в байтовую переменную или нет.

Ответ 3

В момент компиляции компилятор может определить значение конечной переменной, если он назначен во время создания, но во втором коде вы присваиваете значение после создания, которое не будет улавливаться компилятором.

Если вы используете более 127 в первом коде (для переменной i), это тоже не сработает.

Spec говорит: "Если примитивный тип или строка определяется как константа, и значение известно во время компиляции, компилятор заменяет имя константы всюду в коде своим значением. Это называется константой времени компиляции"

И

Постоянная времени компиляции:

объявлено окончательным

примитив или строка

инициализируется в объявлении

инициализируется постоянным выражением