Конечный параметр в методе в 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
Компилятор не будет выполнять неявный приведение, что может привести к потере данных для переменных времени выполнения.