开发者

Java 7 underscore in numeric literals

开发者 https://www.devze.com 2023-03-09 19:11 出处:网络
When开发者_如何转开发 we must use a _ to separate digits in a number I don\'t understand the following case in which I can\'t use it:

When开发者_如何转开发 we must use a _ to separate digits in a number I don't understand the following case in which I can't use it:

In positions where a string of digits is expected

(as documented in the JDK7 guide here)

Some examples?


You don't have to use "_", you can. And examples given in the proposal are credit card numbers, phone numbers, or simply numbers for which it makes sense to have a separator in the code.

For the "In positions where a string of digits is expected" it's simply in places where it's supposed to start (or end) with a digit. Here are some examples.

Note that according to this proposal, underscores can only be placed between digits. They cannot be placed by themselves in positions where a string of digits would normally be expected:

int x1 = _52; // This is an identifier, not a numeric literal.

int x2 = 5_2; // OK. (Decimal literal)

int x2 = 52_; // Illegal. (Underscores must always be between digits)

int x3 = 5_______2; // OK. (Decimal literal.)

int x4 = 0_x52; // Illegal. Can't put underscores in the "0x" radix prefix.

int x5 = 0x_52; // Illegal. (Underscores must always be between digits)

int x6 = 0x5_2; // OK. (Hexadecimal literal)

int x6 = 0x52_; // Illegal. (Underscores must always be between digits)

int x6 = 0x_; // Illegal. (Not valid with the underscore removed)

int x7 = 0_52; // OK. (Octal literal)

int x7 = 05_2; // OK. (Octal literal)

int x8 = 052_; // Illegal. (Underscores must always be between digits)


Resources:

  • OpenJDK - Project Coin - PROPOSAL: Underscores in Numbers (Version 2)
  • Joe Darcy's blog - Project Coin: Project Coin: Literal Grammar Hackery


As written in Javadoc:

In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example, to separate groups of digits in numeric literals, which can improve the readability of your code.

For instance, if your code contains numbers with many digits, you can use an underscore character to separate digits in groups of three, similar to how you would use a punctuation mark like a comma, or a space, as a separator.

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;

You do not have to use it anywhere, but if you want, you can use it everywhere between every digit in numeric literals.

This is especially useful to improving readability:

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


It looks like someone killed the URL in the original post (OP). Here's the whole nasty URL just in case some formatting feature kills it again:

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

The specific quote from that page to which you are speaking is as follows:

You can place underscores only between digits; you cannot place underscores in the following places:

  • At the beginning or end of a number

  • Adjacent to a decimal point in a floating point literal

  • Prior to an F or L suffix

  • In positions where a string of digits is expected

By the way, in an effort to be as persnickety as possible, it should be mentioned that for the third point, you can't use an underscore prior to the D suffix either, as shown in the following example:

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

I too found the third point rather curious. I mean, for the most part, all of the scenarios are covered by the first three points, so what is this mysterious 'string of digits' for which they speak? Which scenario doesn't actually get addressed by the first three points that forces them to add this mysterious fourth?

Initially I thought they were speaking about hexadecimal notation or binary notation, where a number is expected after the b or the x, as with the following examples that don't work:

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

Still, I think that might technically be the same as the first point, which says an underscore can't be at the beginning of the number; but certainly, a 'string of numbers' is expected after a 'b' or an 'x' when using binary or hex, right? So if I was a betting man, I might put some money behind the binary/hexadecimal scenario. But I have another plausible scenario on which I might hedge my bet. Here it goes.

Personally, I wish there was a rule in Java that said you can only use the word 'string' when talking about a java.lang.String. Allowing the term 'string' to retain it's pedestrian meaning causes confusion, and this is a perfect example.

Now, if the fourth point said "In positions where a java.lang.String of digits is expected" I might come to the conclusion that they're talking about actual java.lang.String objects that represent numbers that need to be parsed. So, take this piece of code:

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

Will that compile? Will that run? It will compile fine, but of course, the parseInt method expects a java.lang.String of numbers, and validation or parsing of that numeric java.lang.String will trigger the following error at runtime:

Exception in thread "main" java.lang.NumberFormatException: For input string: "123_456" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:492) at java.lang.Integer.parseInt(Integer.java:527) at Tester.main(Tester.java:7)

Of course, this is a runtime error, and it appears that the Oracle documentation is really speaking about errors that will be flagged at compile time. But this certainly is a scenario where a 'String of numbers' is expected.

Now if only the Oracle documentation was in a Wiki format. It might tempt me to go in and add something like the following:

You can place underscores only between digits; you cannot place underscores in the following places:

  • At the beginning or end of a number

  • Adjacent to a decimal point in a floating point literal

  • Prior to an 'F' or 'L' or 'D' suffix (I added the 'D')

  • Before or after the hexadecimal and binary markers 'x' and 'b'

  • And if you provide a java.lang.String to a method that expects nothing but numbers, expect a runtime exception to be thrown by the parsing algorithm that's being used behind the scenes.

By the way, I just wrote a little article on the topic over at TheServerSide. Feel free to take a look. The article is designed to hit on the Oracle Certified Professional, Java 7 Programmer certification objective, but it's a pretty comprehensive and easy to read article to just generally explain the rules around using underscores.

OCPJP Certification: What you need to know about numeric literals with underscores

Hope that helps.


no idea, but here's the grammar, enjoy. (I don't see "string of digits" anywhere)

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


"In positions where a string of digits is expected" means where a variable of type String which contains digits is expected, then using an underscore will make the underscore part of the number. For example look at the code below:

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

So if you have a method expecting a String of digits as one of the arguments, DO NOT use underscore to separate the digits because it will be treated as any other String.


My interpretation of this is that underscores cannot be placed by themselves in positions where a string of digits would normally be expected:

int x1= _; // Illegal.


I believe the In positions where a string of digits is expected covers things like escape sequences in string literals. For example, you can't say \u00_11.

0

精彩评论

暂无评论...
验证码 换一张
取 消