Ява - короткая и литье - PullRequest
       22

Ява - короткая и литье

11 голосов
/ 27 апреля 2010

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

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) { }

Правильно ли следующее резюме (только в приведенном выше примере с использованием short)?

  • прямая инициализация без приведения возможна только с использованием литералов или отдельных переменных (если значение находится в диапазоне объявленного типа)
  • если относительное значение присваивания относится к выражениям, использующим переменные, необходимо приведение

Но почему именно мне нужно привести аргумент второго вызова метода с учетом предыдущего резюме?

Ответы [ 3 ]

18 голосов
/ 27 апреля 2010

Это соответствующие разделы JLS:

JLS 5.1.1 Преобразование удостоверений

Преобразование из типа в тот же тип разрешено для любого типа.

JLS 5.2 Преобразование присвоения

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

  • Преобразование личности
  • [...]

Кроме того, если выражение является константным выражением типа byte, short, char или int:

  • Может использоваться сужающее примитивное преобразование, если тип переменной равен byte, 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!

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

JLS 5.3. Преобразование вызова метода

Преобразования вызова метода, в частности, не включают в себя неявное сужение целочисленных констант, которое является частью преобразования присваивания. Разработчики языка программирования Java считали, что включение этих неявных сужающих преобразований добавит дополнительную сложность процессу разрешения сопоставления перегруженного метода.

Вместо того, чтобы объяснять, как именно работает метод разрешения, я просто процитирую Effective Java 2nd Edition , пункт 41: Используйте перегрузку разумно:

Правила, определяющие, какая перегрузка выбрана, чрезвычайно сложны. Они занимают тридцать три страниц в спецификации языка, и лишь немногие программисты понимают все их тонкости.


Смотри также

1 голос
/ 27 апреля 2010

«7» в вызове test(7); является int и не будет автоматически преобразовано в short.

Это работает, когда вы объявляете и инициализируете значения short, но это особый случай для компилятора. Этот особый случай не существует для вызовов методов.

1 голос
/ 27 апреля 2010

Результат арифметической операции со значениями short всегда равен int. test(7) не работает, так как вы еще не сказали, что 7 имеет тип short. Компилятор должен быть немного умнее.

...