char и байт с окончательным модификатором доступа - java

Пожалуйста, взгляните на приведенный ниже пример, я не могу понять связь между символом и байтом.

byte b = 1;
char c = 2;

c = b; // line 1

Дайте мне ошибку компиляции, потому что c - это тип char, а b - тип byte, поэтому приведение должно быть в таком состоянии

но теперь самое интересное, когда я запускаю код ниже

final byte b = 1;
char c = 2;

c = b; // line 2

строка 2 успешно компилируется, ей вообще не нужно приведение, поэтому мой вопрос в том, почему char c ведет себя по-другому, когда я использую окончательный модификатор доступа с byte


person Nirav Prajapati    schedule 20.11.2014    source источник


Ответы (3)


Поскольку уточнение с помощью final делает переменную постоянной переменной, которая представляет собой константное выражение. Так

final byte b = 1;
char c = 2;

c = b; // line 2

на самом деле становится

final byte b = 1;
char c = 2;

c = 1;

И у компилятора есть гарантия, что значение 1 может поместиться в переменную char.

С непостоянной переменной byte такой гарантии нет. byte подписано, char не подписано.

person Sotirios Delimanolis    schedule 20.11.2014

Вы сталкиваетесь с JLS- 5.1.4 Расширение и сужение примитивного преобразования,

Следующее преобразование сочетает в себе как расширяющие, так и сужающие примитивные преобразования:

  • byte to char

Во-первых, byte преобразуется в int посредством расширяющего примитивного преобразования (§5.1.2), а затем полученный int преобразуется в char путем сужающего примитивного преобразования (§5.1.3).

final byte b = 1;
char c = (char) ((int) 2); // <-- 2 is an int literal
c = (char) ((int) 1); // <-- b is 1 a byte literal

Если вы изучите байт-коды с javap -v, вы увидите, что значение 1 уже заменило переменную b после компиляции.

public static void main(java.lang.String[]) throws java.lang.Exception;
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Exceptions:
    throws java.lang.Exception
  Code:
    stack=2, locals=3, args_size=1
       0: iconst_1 
       1: istore_1 // b = 1
       2: iconst_2
       3: istore_2 // c = 2
       4: iconst_1 // integer1.
       5: istore_2 // c = 1.
person Elliott Frisch    schedule 20.11.2014

Я предполагаю, что это происходит потому, что java-компилятор заменяет ссылки на final переменных их значениями (почти как препроцессор в C). Поскольку значение 1 допустимо для типа char, последняя строка преобразуется в

c = 1;

который успешно скомпилирован.

person AlexR    schedule 20.11.2014
comment
final переменные с постоянными выражениями. то есть byte a=1; final b=a; char c=b; по-прежнему не работает. - person weston; 20.11.2014