Java 7 подчеркивание в числовых литералах - PullRequest
53 голосов
/ 02 июня 2011

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

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

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

Несколько примеров?

Ответы [ 8 ]

58 голосов
/ 02 июня 2011

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

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

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

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_; // Незаконно. (Подчеркивание всегда должно быть между цифрами)


Ресурсы:

27 голосов
/ 31 июля 2013

Как написано в 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;
5 голосов
/ 31 декабря 2011

Похоже, что кто-то убил 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: Что нужно знать о числовых литералах с подчеркиванием

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

3 голосов
/ 02 июня 2011

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

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
2 голосов
/ 23 октября 2017

TL; TR;

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

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

10_000_000_000 // Is equal to 10000000000
7_687_316_418_138_483.345_938 // Is equal to 7687316418138483.345938
2 голосов
/ 10 октября 2013

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

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

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

2 голосов
/ 26 июня 2012

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

2 голосов
/ 02 июня 2011

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

int x1= _; // Illegal.
...