Буквальний xyz типу int виходить за межі діапазону


90

На даний момент я працюю з типами даних на 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 дають різні (на мій погляд кращі) повідомлення про помилки щодо цієї проблеми.
Йоахім Зауер,

Відповіді:


195

Додайте капітал Lдо кінця:

long value = 9223372036854775807L;

В іншому випадку компілятор спробує проаналізувати літерал як int, отже, повідомлення про помилку


4
Це в специфікаціях мови Java. Повний текст знайдіть тут
Лукас Едер,

@Lukas, довге значення = 00000077029062100L; дає мені ту саму помилку, і вона менше 19 цифр. будь-яка ідея, чому вона кидає "Буквальний 0000007702062100L типу long поза межами досяжності"
Santossh Kumhar

1
@SantosshKumhar: Це вісімковий літерал , який не може містити цифр 8або 9. Видаліть перші нулі.
Лукас Едер,

50

Я не знаю, чому це посилається на довгий тип даних як 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 коротших відповідей ;-) Також: допомога в інтерпретації повідомлення про помилку (сподіваюся) означає менше запитань "що означає це повідомлення про помилку".
Йоахім Зауер,

Ваша відповідь дуже хороша ... без сумніву, саме тому голосуйте за, але будь ласка, відредагуйте її, а вгорі (початок Вашої відповіді) просто напишіть в 1 рядок точне рішення проблеми, а потім нижче своє пояснення. Оскільки багато людей шукають швидкого рішення, а не глибоких пояснень
Ширіш Ервад

4
Вони можуть вільно переглядати інші другі відповіді (найголосніша навіть дає швидке рішення). Я думаю, що навчання людей про те, як розбирати та розуміти повідомлення про помилки, є кориснішим у довгостроковій перспективі, ніж просто робити це за них. «Дай людині рибу ...» і все таке.
Йоахім Зауер

Дякую за примітку.
Венкатеш Гуд

19

Спробуйте зробити 9223372036854775807L. У Lкінці повідомляє Java, що 9223372036854775807це long.


0

У мене була ця проблема в минулому, і я виправив це, написавши значення в науковій формі. наприклад:

double val = 9e300;

-2
long ak = 34778754226788444L/l;

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

Навіщо використовувати L / l? Оскільки long є частиною цілісного типу даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.