Java 7 подчеркивание в числовых литералах

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

В позициях, где ожидается строка цифр

(как описано в руководстве по JDK7 здесь)

Некоторые примеры?

8 ответов

Вы не должны использовать "_", вы можете. И примерами, приведенными в предложении, являются номера кредитных карт, номера телефонов или просто номера, для которых имеет смысл иметь разделитель в коде.

Для "В позициях, где ожидается строка цифр", это просто в местах, где он должен начинаться (или заканчиваться) цифрой. Вот несколько примеров.

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

int x1 = _52; // Это идентификатор, а не числовой литерал.

int x2 = 5_2; // ХОРОШО. (Десятичный литерал)

int x2 = 52_; // Незаконно. (Подчеркивание всегда должно быть между цифрами)

int x3 = 5_______2; // ХОРОШО. (Десятичный литерал.)

int x4 = 0_x52; // Незаконно. Невозможно поставить подчеркивание в префиксе "0x".

int x5 = 0x_52; // Незаконно. (Подчеркивание всегда должно быть между цифрами)

int x6 = 0x5_2; // ХОРОШО. (Шестнадцатеричный литерал)

int x6 = 0x52_; // Незаконно. (Подчеркивание всегда должно быть между цифрами)

int x6 = 0x_; // Незаконно. (Недействительно с удаленным подчеркиванием)

int x7 = 0_52; // ХОРОШО. (Восьмеричное буквальное)

int x7 = 05_2; // ХОРОШО. (Восьмеричное буквальное)

int x8 = 052_; // Незаконно. (Подчеркивание всегда должно быть между цифрами)


Ресурсы:

Как написано в Javadoc:

В Java SE 7 и более поздних версиях любое число символов подчеркивания (_) может появляться в любом месте между цифрами числового литерала. Эта функция позволяет, например, разделять группы цифр в числовых литералах, что может улучшить читаемость вашего кода.

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

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi =  3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

TL;TR;

Вам не нужно нигде использовать его, но если вы хотите, вы можете использовать его везде между каждой цифрой.

Это особенно полезно для улучшения читабельности:

10_000_000_000 // Is equal to 10000000000
7_687_316_418_138_483.345_938 // Is equal to 7687316418138483.345938

Похоже, кто-то убил URL в оригинальном сообщении (OP). Вот весь неприятный URL на случай, если какая-то функция форматирования убьет его снова:

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Конкретная цитата с той страницы, с которой вы разговариваете, выглядит следующим образом:

Вы можете поместить подчеркивание только между цифрами; Вы не можете разместить подчеркивание в следующих местах:

  • В начале или конце числа

  • Смежный с десятичной точкой в ​​литерале с плавающей точкой

  • До суффикса F или L

  • В позициях, где ожидается строка цифр

Кстати, чтобы быть максимально привередливым, следует упомянуть, что для третьего пункта нельзя использовать подчеркивание перед суффиксом D, как показано в следующем примере:

double trouble = 123.456_D;  //fail
float myBoat = 321.123_F;  //fail
long winded = 90210_L;  //fail

Третий пункт мне тоже показался довольно любопытным. Я имею в виду, что по большей части все сценарии охватываются первыми тремя пунктами, так что же это за таинственная "цепочка цифр", за которую они говорят? Какой сценарий фактически не рассматривается первыми тремя пунктами, что вынуждает их добавить этот загадочный четвертый?

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

byte size = 0_b111101;  //fail
byte me = 0b_111101;  //fail
int hexed = 0_x_BABE;  //fail

Тем не менее, я думаю, что технически это может быть то же самое, что и первая точка, которая говорит, что подчеркивание не может быть в начале числа; но, разумеется, после "b" или "x" ожидается "строка чисел" при использовании двоичного или шестнадцатеричного кода, верно? Так что, если бы я был игроком на пари, я мог бы положить немного денег за двоичный / шестнадцатеричный сценарий. Но у меня есть другой вероятный сценарий, по которому я мог бы застраховать свою ставку. Здесь это идет.

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

Теперь, если четвертый пункт говорит: "В позициях, где ожидается строка цифр java.lang.String", я мог бы прийти к выводу, что они говорят о реальных объектах java.lang.String, которые представляют числа, которые необходимо проанализировать. Итак, возьмите этот кусок кода:

int i = Integer.parseInt("123_456");

Будет ли это компилироваться? Будет ли это работать? Он скомпилируется нормально, но, конечно, метод parseInt ожидает java.lang.String чисел, а проверка или анализ этого числового java.lang.String вызовет следующую ошибку во время выполнения:

Исключение в потоке "main" java.lang.NumberFormatException: для входной строки: "123_456" в java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) в java.lang.Integer.parseInt(Integer.java:492) в java.lang.Integer.parseInt(Integer.java:527) в Tester.main(Tester.java:7)

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

Теперь, если бы только документация Oracle была в формате Wiki. Это может соблазнить меня пойти и добавить что-то вроде следующего:

Вы можете поместить подчеркивание только между цифрами; Вы не можете разместить подчеркивание в следующих местах:

  • В начале или конце числа

  • Смежный с десятичной точкой в ​​литерале с плавающей точкой

  • До суффикса "F" или "L" или "D" (я добавил "D")

  • До или после шестнадцатеричных и двоичных маркеров "x" и "b"

  • И если вы предоставляете java.lang.String для метода, который не ожидает ничего, кроме чисел, ожидайте, что исключение во время выполнения будет сгенерировано алгоритмом синтаксического анализа, который используется за кулисами.

Кстати, я только что написал небольшую статью на эту тему на TheServerSide. Не стесняйтесь взглянуть. Статья предназначена для достижения цели сертификации Oracle Certified Professional, сертификации Java 7 Programmer, но это довольно всеобъемлющая и легкая для чтения статья, в которой просто в общих чертах объясняются правила использования подчеркивания.

Сертификация OCPJP: Что нужно знать о числовых литералах с подчеркиванием

Надеюсь, это поможет.

Понятия не имею, но вот грамматика, наслаждайтесь. (Я нигде не вижу "цепочку цифр")

http://download.oracle.com/otndocs/jcp/enhancements-0.875-pr-oth-JSpec/

IntegerLiteral:
    DecimalIntegerLiteral 
    HexIntegerLiteral 
    OctalIntegerLiteral 
    BinaryIntegerLiteral 

BinaryIntegerLiteral:
    BinaryNumeral IntegerTypeSuffixopt 

BinaryNumeral:
    0 b BinaryDigits 
    0 B BinaryDigits 

DecimalNumeral:
    0 
    NonZeroDigit Digitsopt 
    NonZeroDigit Underscores Digits 

Underscores:
    _ 
    Underscores _ 

Digits:
    Digit
    Digit DigitsAndUnderscoresopt Digit

DigitsAndUnderscores:
    DigitOrUnderscore
    DigitsAndUnderscores DigitOrUnderscore

DigitOrUnderscore:
    Digit
    _

HexDigits:
    HexDigit 
    HexDigit HexDigitsAndUnderscoresopt HexDigit 

HexDigitsAndUnderscores:
    HexDigitOrUnderscore 
    HexDigitsAndUnderscores HexDigitOrUnderscore 

HexDigitOrUnderscore:
    HexDigit 
    _ 

OctalNumeral:
    0 OctalDigits 
    0 Underscores OctalDigits 

OctalDigits:
    OctalDigit 
    OctalDigit OctalDigitsAndUnderscoresopt OctalDigit 

OctalDigitsAndUnderscores:
    OctalDigitOrUnderscore 
    OctalDigitsAndUnderscores OctalDigitOrUnderscore 

OctalDigitOrUnderscore:
    OctalDigit 
    _ 

BinaryDigits:
    BinaryDigit 
    BinaryDigit BinaryDigitsAndUnderscoresopt BinaryDigit 

BinaryDigitsAndUnderscores:
    BinaryDigitOrUnderscore 
    BinaryDigitsAndUnderscores BinaryDigitOrUnderscore 

BinaryDigitOrUnderscore:
    BinaryDigit
    _ 

BinaryDigit: one of
    0 1

"В позициях, где ожидается строка цифр" означает, что ожидается переменная типа String, которая содержит цифры, тогда использование подчеркивания сделает подчеркивание частью числа. Например, посмотрите на код ниже:

int num = 999_333;    
String anum = "999_333";
System.out.println(num);   //Outputs 999333
System.out.println(anum);  //Outputs 999_333

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

Моя интерпретация этого заключается в том, что подчеркивания не могут быть размещены сами по себе в положениях, где обычно ожидается строка цифр:

int x1= _; // Illegal.

Я считаю, что "В позициях, где ожидается строка цифр", охватывает такие вещи, как escape-последовательности в строковых литералах. Например, вы не можете сказать "\u00_11".

Другие вопросы по тегам