У меня есть следующий фрагмент кода.
public static void main(String[] args) {
short a = 4;
short b = 5;
short c = 5 + 4;
short d = a;
short e = a + b; // does not compile (expression treated as int)
short z = 32767;
short z_ = 32768; // does not compile (out of range)
test(a);
test(7); // does not compile (not applicable for arg int)
}
public static void test(short x) { }
Действительно ли следующее сводное корректный (только относительно примера выше использования короткого)?
Но почему точно я должен бросить аргумент второго вызова метода, принимающего во внимание предыдущую сводку?
Это соответствующие разделы JLS:
Преобразование из типа в тот же самый тип разрешено для любого тип.
Преобразование присвоения происходит, когда значение выражения присваивается переменной: тип выражения должен быть преобразован в тип переменной. Контексты присваивания позволяют использовать одно из следующего:
- Преобразование идентичности
- [...]
Кроме того, если выражение является константным выражением типа
byte
,short
,char
илиint
:
- Может использоваться сужающее примитивное преобразование, если тип переменной -
байт
,short
илиchar
, а значение константного выражения может быть представлено в виде переменной.
Приведенные выше правила объясняют все следующее:
short a = 4; // representable constant
short b = 5; // representable constant
short c = 5 + 4; // representable constant
short d = a; // identity conversion
short e = a + b; // DOES NOT COMPILE! Result of addition is int
short z = 32767; // representable constant
short z_ = 32768; // DOES NOT COMPILE! Unrepresentable constant
Что касается того, почему это не компилируется:
test(7); // DOES NOT COMPILE! There's no test(int) method!
Это потому, что сужающее преобразование с константой определено только для присваиваний; не для вызова метода, который имеет совершенно другие правила.
Преобразование вызова метода конкретно не включает неявное сужение целочисленных констант, которое является частью преобразования присваивания. Разработчики языка программирования Java чувствовали, что включение этих неявных сужающих преобразований добавит дополнительной сложности к процессу разрешения сопоставления перегруженных методов.
Вместо того, чтобы объяснять, как именно работает разрешение метода, я просто процитирую Эффективное 2-е издание Java , пункт 41: разумно используйте перегрузку:
Правила, определяющие, какая перегрузка выбрана, чрезвычайно сложны. Они занимают тридцать три страниц в спецификации языка, и немногие программисты понимают все их тонкости.
short x = 3; x + = 4.6;
компилируется из-за семантики составного присваивания '7' в тесте вызова (7);
является int
и не будет автоматически преобразовываться в сокращенное значение
.
Это работает, когда вы объявляете и инициализируете короткие
значения, но это особый случай для компилятора. Этот особый случай не существует для вызовов методов.
Результатом арифметической операции над короткими
значениями всегда является int
. test (7)
не работает, поскольку вы не сказали, что 7 имеет тип short
. Компилятор здесь должен быть немного умнее.