Подтвердить что ты не робот

Почему я могу назначить целочисленный литерал для переменной короткого типа, но не для параметра метода короткого типа?

Почему я могу это сделать:

short a = 5;

Но не это:

void setNum(short a);

setNum(5);

Он выбрасывает:

Возможное преобразование с потерями из int в короткий

Я понимаю, что 5 является целым литералом, и вы должны его бросить. Я также понимаю, что если значение не является константой, то очевидно, что ему нужно выбросить эту ошибку, потому что, возможно, значение достигает предела короткого типа. Но почему, если компилятор знает, что я передаю константу, которую может удерживать короткая (как в задании), она не позволяет ее скомпилировать? Я имею в виду, в чем разница между ними?

4b9b3361

Ответ 1

Чтобы понять, почему преобразование типа присваивания работает, в то время как вызов отклоняется, нужно обратиться к теме спецификации Java Language Specification для сужения примитивные преобразования и контекст этого преобразования: контекст назначения и контекст вызова.

Согласно JLS, сужение примитивного преобразования допускается в контексте назначения, если:

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

..., который соответствует вашему случаю с int константой 5 при назначении short a.

В контексте вызова не допускается такое сужение примитивного преобразования, что объясняет, почему ваш вызов setNum(short) терпит неудачу при передаче константы int 5.

Но почему, если компилятор знает, что я передаю константу, которую может удерживать короткая (как в задании), она не позволяет ее скомпилировать? Я имею в виду, в чем разница между ними?

JLS, возможно, не захотел обременять компиляторы этой дополнительной логикой. В случае обращения аргумент, сопоставляемый по типу с формальным параметром, является выражением - компилятор уже должен определить тип, но не нужно также проверять, можно ли сузить значение выражения. В этом случае, будучи константой, нам ясно, что это может быть, но в контексте выполнения компилятору разрешено не беспокоиться об этой проверке и на самом деле правильно отклонить его.

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

То же самое верно в числовом контексте, поэтому объявление:

short a = 5;short b = a * 5;

... аналогичным образом не допускается, несмотря на то, что он четко состоит из констант, которые достаточно узки.

Ответ 2

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

Целые числа могут содержать 32 бита данных, тогда как шорты могут содержать только 16 бит данных. Так, например (на самом деле цифры были бы намного больше), значение int было равно 50, и затем вы отбрасывали его на короткий, данные были бы сокращены до "5" , потому что короткий не имеет достаточно большое выделение памяти.

Этот код, который вы опубликовали, не будет работать, потому что, когда вы определяете краткое, как показано ниже:

short a = 5;

Вы создаете короткое число, и число достаточно мало, чтобы короткое могло удерживать его. Когда вы вводите только "5" в качестве аргумента метода, он обрабатывается как целое число, а JVM не знает, что он небольшой и безопасный, чтобы сделать короткий. Чтобы сделать "5" подходящим в качестве аргумента для метода, вам нужно превратить его в короткий, используя сужение преобразования, следующим образом:

setNum((short) 5);

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

(Здесь приведена некоторая документация Oracle)