Конечный параметр в методе в java

У меня есть 2 вопроса с этими сегментами кода

  • метод 1 работает нормально, а метод 2 - нет. В чем причина этого?
  • В методе 1 возвращаемое значение является байтом (8 бит). Но мы действительно возвращаем значение char (16 бит). что на самом деле происходит здесь?

//метод 1

static byte m1() {
    final char c = 'b'-'a';
    return c; 
}

//метод 2

static byte m3(final char c) {
    return c; // 3
}

Ответы

Ответ 1

char в Java - это 16-разрядное значение без знака, а byte - 8-значное значение знака. Допустимый диапазон для байта [-128, 127]. Таким образом, не все символы могут быть назначены в byte.

В первом методе вы возвращаете char с кодовой точкой = 1 ('b' - 'a'). Теперь, поскольку вы определили char как final и присваиваете ему постоянное выражение, оно становится постоянной времени компиляции. Таким образом, компилятор не дает ошибок компилятора.

Из JLS Раздел 5.2:

Если выражение является константным выражением (§15.28) типа byte, short, char или int:
    - Сужение примитивного преобразования может быть использовано, если тип переменной является байтом, коротким или char, а значение константного выражения представляется в типе переменной.

Акцент на мой.

Однако, если вы внесете c нефинал, это также приведет к ошибке компилятора:

static byte m1() {  // This will be an error
    char c = 'b'-'a';
    return c; 
}

Причина в том, что c больше не является константой времени компиляции, а компилятор не делает неявного downcast.

Во втором методе вы возвращаете char, который вы передали. Параметр c не имеет постоянной времени компиляции. Во время компиляции неизвестно, какое значение может получить метод. Например, если вы передаете char с кодовыми точками не в допустимом значении byte, это не сработает.

Чтобы сделать 2-й способ работы, вы можете сделать явное приведение:

static byte m3(final char c) {
    return (byte)c; // 3
}

Ответ 2

В m1() компилятор видит, что char c является константой со значением 1 и поэтому не жалуется, так как знает, что он может быть помещен в байты. Если вы изменили его на final char c = 128, где 127 - максимальный размер byte, вы получите жалобу, так же как и вы удалили дескриптор переменной final из char c.

Ответ 3

В методе 2 компилятор не может сузить неявный отбор из чата в байт, потому что это может привести к потере точности (Java поддерживает символы Unicode, а его примитивный тип char определяется размером 16- бит информации, в отличие от языка C, где обычно 8 бит)

В методе 1, однако, компилятор может определить, что постоянное значение 'b' - 'a' на самом деле не приведет к потере точности, и поэтому позволяет выполнять неявное преобразование.

Взгляните на: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

Ответ 4

Теперь причина m1() работает, а m3() - нет, потому что в m1() c есть compile-time constant.

Проанализируйте этот код:

    byte b = 'x'; //compile-time constant
    int i = 'x'; //compile-time constant
    char c = 'x'; //compile-time constant
    c = i; //compilation error
    c = b; //compilation error
    b = i; //compilation error
    b = c; //compilation error
    i = b;  // Okay
    i = c;  // Okay

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