Литерал xyz типа int вне допустимого диапазона

93

В настоящее время я работаю с типами данных на Java, и, если я правильно понял, тип longпринимает значение в диапазоне от -9,223,372,036,854,775,808 до +9,223,372,036,854,775,807. Теперь, как вы можете видеть ниже, я создал longпеременную с именем testLong, хотя, когда я вставляю 9223372036854775807 в качестве значения, я получаю сообщение об ошибке:

Литерал 9223372036854775807 типа int находится вне допустимого диапазона.

Я не знаю, почему этот longтип данных относится к типу данных int.

У кого-нибудь есть идеи?

Код:

char testChar = 01;
byte testByte = -128;
int testInt = -2147483648;
short testShort = -32768;
long testLong = 9223372036854775807;
float testFoat;
double testDouble = 4.940656458412;
boolean testBool = true;
Мэтью Доннан
источник
Кстати: какой компилятор вы используете? И Eclipse, и компилятор Sun JDK выдают разные (на мой взгляд, лучше) сообщения об ошибках для этой проблемы.
Иоахим Зауэр

Ответы:

200

В Lконце добавьте заглавную букву:

long value = 9223372036854775807L;

В противном случае компилятор попытается проанализировать литерал как символ int, поэтому сообщение об ошибке

Лукас Эдер
источник
4
Это в спецификациях языка Java. Полный текст можно
Лукас Эдер
@Lukas, длинное значение = 00000077029062100L; дает мне ту же ошибку, и это меньше 19 цифр. любая идея, почему он бросает «Буквальный 0000007702062100L типа long вне допустимого диапазона»
Brooklynn99
1
@SantosshKumhar: Это восьмеричный литерал , который не может содержать цифр 8или 9. Удалите ведущие нули.
Лукас Эдер
51

Я не знаю, почему он относится к длинному типу данных как к int

Нет. Вы должны научиться доверять сообщениям компилятора (особенно если они поступают от нормальных современных компиляторов, а не от старых компиляторов C / C ++). Хотя язык, на котором они говорят, иногда бывает трудно расшифровать, обычно они не лгут вам.

Посмотрим на это еще раз:

Литерал int 9223372036854775807 находится вне допустимого диапазона.

Обратите внимание, что в нем нигде не упоминается ваша переменная testLongили тип long, поэтому речь не идет об инициализации. Проблема, кажется, возникает в другом месте.

Теперь давайте исследуем некоторые части сообщения:

  • intсообщает нам, что хочет рассматривать что-то как intценность (а это не то, что вы хотели!)
  • "вне диапазона" довольно ясно: что-то не в ожидаемом диапазоне (возможно, int )
  • «Буквальный»: вот что интересно: что такое буквальный?

Я оставлю удобный список, чтобы поговорить на мгновение о литералах: литералы - это места, где у вас есть некоторая ценность в вашем коде. Есть Stringлитералы, intлитералы, classлитералы и так далее. Каждый раз, когда вы явно упоминаете значение в своем коде, это литерал.

Так что на самом деле вас не беспокоит объявление переменной, а само число, значение - вот что вас беспокоит.

Вы можете легко проверить это, используя один и тот же литерал в контексте, где a longи an intодинаково приемлемы:

System.out.println(9223372036854775807);

PrintStream.printlnможет принимать либо илиintlong (или почти что угодно еще). Так что с этим кодом все должно быть хорошо?

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

Проблема в том, что «некоторые цифры» определены как intлитералы и, следовательно, должны находиться в диапазоне, определяемом int.

Если вы хотите написать longлитерал, вы должны сделать это явным, добавив L(или нижний регистр l, но я настоятельно рекомендую вам всегда использовать вариант в верхнем регистре, потому что его намного легче читать и сложнее принять за а 1).

Обратите внимание, что аналогичная проблема возникает с float(postfix F/ f) и double(postfix D/d ).

Боковое примечание: вы поймете, что литералов byteили нет, shortи вы все еще можете присваивать значения (обычно intлитералы) byteи shortпеременным: это возможно из-за специальных правил в § 5.2 о Конверсии присвоения : они позволяют присваивать постоянные выражения большего типа к byte, short, charили , int если значения находятся в пределах типов диапазона.

Иоахим Зауэр
источник
3
Откуда у вас время ;-)
Лукас Эдер
3
@Lukas: Иногда я пишу такие ответы в надежде, что мне не придется писать для них 300 более коротких ;-) Также: помощь в интерпретации сообщения об ошибке (надеюсь) означает меньше вопросов "что означает это сообщение об ошибке".
Иоахим Зауэр
ваш ответ очень хорош ... без сомнения, поэтому проголосуйте за, но, пожалуйста, отредактируйте его и в верхней части (начало вашего ответа) просто напишите в одной строке точное решение проблемы, а затем под своим объяснением. Потому что многие люди ищут быстрое решение, а не глубокое объяснение
Шириш Хервэйд,
4
Они могут посмотреть другие вторые ответы (тот, который получил наибольшее количество голосов, даже дает быстрое решение). Я думаю, что обучение людей тому, как анализировать и понимать сообщения об ошибках, более полезно в долгосрочной перспективе, чем просто делать это за них. «Дайте человеку рыбу ...» и все такое.
Иоахим Зауэр,
Спасибо за примечание.
Венкатеш Гуд
19

Попробуйте сделать 9223372036854775807L. В Lконце указывает Java, что 9223372036854775807это long.

Jontro
источник
0

У меня была эта проблема в прошлом, и я исправил ее, записав значение в научной форме. например:

double val = 9e300;

источник
-2
long ak = 34778754226788444L/l;

Оба используют, но одновременно только один использует заглавную L или строчную l.

Зачем использовать л / л? Потому что long является частью интегрального типа данных.

Аккушваха
источник