web-dev-qa-db-fra.com

Java 7 soulignement en littéraux numériques

Lorsque nous devons utiliser un _ pour séparer les chiffres d'un nombre, je ne comprends pas le cas suivant dans lequel je ne peux pas l'utiliser:

Aux positions où une chaîne de chiffres est attendue

(comme documenté dans le guide JDK7 ici )

Quelques exemples?

54
xdevel2000

Vous n'avez pas pour utiliser "_", vous pouvez . Et des exemples donnés dans la proposition sont des numéros de carte de crédit, des numéros de téléphone ou tout simplement des numéros pour lesquels il est logique d'avoir un séparateur dans le code.

Pour les "Aux positions où une chaîne de chiffres est attendue", c'est simplement aux endroits où il est censé commencer (ou se terminer) par un chiffre. Voici quelques exemples.

Notez que selon cette proposition, les soulignements ne peuvent être placés qu'entre les chiffres. Ils ne peuvent pas être placés seuls dans des positions où une chaîne de chiffres serait normalement attendue:

int x1 = _52; // Ceci est un identifiant, pas un littéral numérique.

int x2 = 5_2; // D'ACCORD. (Littéral décimal)

int x2 = 52_; // Illégal. (Les caractères de soulignement doivent toujours être entre les chiffres)

int x3 = 5_______2; // D'ACCORD. (Littéral décimal.)

int x4 = 0_x52; // Illégal. Impossible de mettre des traits de soulignement dans le préfixe de radix "0x".

int x5 = 0x_52; // Illégal. (Les caractères de soulignement doivent toujours être entre les chiffres)

int x6 = 0x5_2; // D'ACCORD. (Littéral hexadécimal)

int x6 = 0x52_; // Illégal. (Les caractères de soulignement doivent toujours être entre les chiffres)

int x6 = 0x_; // Illégal. (Non valide avec le trait de soulignement supprimé)

int x7 = 0_52; // D'ACCORD. (Littéral octal)

int x7 = 05_2; // D'ACCORD. (Littéral octal)

int x8 = 052_; // Illégal. (Les caractères de soulignement doivent toujours être entre les chiffres)


Ressources:

59
Colin Hebert

Comme écrit en Javadoc :

Dans Java SE 7 et versions ultérieures, un nombre quelconque de caractères de soulignement (_) peut apparaître n'importe où entre les chiffres d'un littéral numérique. Cette fonction vous permet, par exemple, de séparer des groupes de chiffres dans des littéraux numériques , ce qui peut améliorer la lisibilité de votre code.

Par exemple, si votre code contient des nombres à plusieurs chiffres, vous pouvez utiliser un caractère de soulignement pour séparer les chiffres par groupes de trois, de la même manière que vous utiliseriez un signe de ponctuation comme une virgule ou un espace comme séparateur.

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;
27
Vinu

Il semble que quelqu'un ait tué l'URL dans le message d'origine (OP). Voici l'URL entière au cas où une fonctionnalité de formatage la tue à nouveau:

http://docs.Oracle.com/javase/tutorial/Java/nutsandbolts/datatypes.html

La citation spécifique de cette page à laquelle vous parlez est la suivante:

Vous pouvez placer des traits de soulignement uniquement entre les chiffres; vous ne pouvez pas placer de soulignement aux endroits suivants:

  • Au début ou à la fin d'un numéro

  • Adjacent à un point décimal dans un littéral à virgule flottante

  • Avant un suffixe F ou L

  • Aux positions où une chaîne de chiffres est attendue

Soit dit en passant, dans un effort pour être aussi persévérant que possible, il convient de mentionner que pour le troisième point, vous ne pouvez pas non plus utiliser un trait de soulignement avant le suffixe D, comme indiqué dans l'exemple suivant:

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

Moi aussi, j'ai trouvé le troisième point assez curieux. Je veux dire, pour la plupart, tous les scénarios sont couverts par les trois premiers points, alors quelle est cette mystérieuse "chaîne de chiffres" dont ils parlent? Quel scénario n'est pas réellement abordé par les trois premiers points qui les obligent à ajouter ce mystérieux quatrième?

Au début, je pensais qu'ils parlaient de notation hexadécimale ou de notation binaire, où un nombre est attendu après le b ou le x, comme avec les exemples suivants qui ne fonctionnent pas:

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

Pourtant, je pense que cela pourrait être techniquement le même que le premier point, qui dit qu'un trait de soulignement ne peut pas être au début du numéro; mais certainement, une "chaîne de nombres" est attendue après un "b" ou un "x" lors de l'utilisation de binaire ou hexadécimal, non? Donc, si j'étais un parieur, je pourrais mettre de l'argent derrière le scénario binaire/hexadécimal. Mais j'ai un autre scénario plausible sur lequel je pourrais couvrir mon pari. Ça y est.

Personnellement, je souhaite qu'il y ait une règle dans Java qui dit que vous ne pouvez utiliser le mot 'chaîne' que lorsque vous parlez d'un Java.lang.String. Permettre au terme 'chaîne' de conserver son caractère piéton le sens provoque la confusion, et ceci est un exemple parfait.

Maintenant, si le quatrième point disait "Aux positions où une chaîne Java.lang.String de chiffres est attendue", je pourrais conclure qu'ils parlent d'objets Java.lang.String réels qui représentent des nombres qui doivent être analysés. Alors, prenez ce morceau de code:

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

Cela compilera-t-il? Est-ce que ça va marcher? Il se compilera correctement, mais bien sûr, la méthode parseInt attend une Java.lang.String de nombres, et la validation ou l'analyse de cette Java.lang.String numérique déclenchera l'erreur suivante au moment de l'exécution:

Exception dans le thread "principal" Java.lang.NumberFormatException: pour la chaîne d'entrée: "123_456" sur Java.lang.NumberFormatException.forInputString (NumberFormatException.Java:65) sur Java.lang.Integer.parseInt (Integer.Java:492) sur Java.lang.Integer.parseInt (Integer.Java:527) sur Tester.main (Tester.Java:7)

Bien sûr, il s'agit d'une erreur d'exécution et il semble que la documentation Oracle parle vraiment d'erreurs qui seront signalées au moment de la compilation. Mais c'est certainement un scénario où une "chaîne de nombres" est attendue.

Maintenant, si seulement la documentation Oracle était au format Wiki. Cela pourrait me tenter d'entrer et d'ajouter quelque chose comme ceci:

Vous pouvez placer des traits de soulignement uniquement entre les chiffres; vous ne pouvez pas placer de soulignement aux endroits suivants:

  • Au début ou à la fin d'un numéro

  • Adjacent à un point décimal dans un littéral à virgule flottante

  • Avant un suffixe "F", "L" ou "D" (j'ai ajouté le "D")

  • Avant ou après les marqueurs hexadécimaux et binaires "x" et "b"

  • Et si vous fournissez un Java.lang.String à une méthode qui n'attend rien d'autre que des nombres, attendez-vous à une exception d'exécution qui sera levée par l'algorithme d'analyse qui est utilisé en arrière-plan.

Soit dit en passant, je viens d'écrire un petit article sur le sujet sur TheServerSide. N'hésitez pas à y jeter un œil. L'article est conçu pour toucher l'Oracle Certified Professional, Java 7 Objectif de certification de programmeur, mais c'est un article assez complet et facile à lire pour expliquer généralement les règles d'utilisation des traits de soulignement.

Certification OCPJP: ce que vous devez savoir sur les littéraux numériques avec des traits de soulignement

J'espère que cela pourra aider.

5
Cameron McKenzie

aucune idée, mais voici la grammaire, profitez-en. (Je ne vois "chaîne de chiffres" nulle part)

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
3
irreputable

TL; TR;

Vous ne devez pas l'utiliser n'importe où, mais si vous le souhaitez, vous pouvez l'utiliser partout entre chaque chiffre.

Ceci est particulièrement utile pour améliorer la lisibilité:

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

Mon interprétation de ceci est que les traits de soulignement ne peuvent pas être placés par eux-mêmes dans des positions où une chaîne de chiffres serait normalement attendue:

int x1= _; // Illegal.
2
dogbane

Je crois que le dans les positions où une chaîne de chiffres est attendue couvre des choses comme les séquences d'échappement dans les littéraux de chaîne. Par exemple, vous ne pouvez pas dire \u00_11.

2
John Spicer

"Dans les positions où une chaîne de chiffres est attendue" signifie où une variable de type Chaîne qui contient des chiffres est attendue, puis l'utilisation d'un trait de soulignement fera la partie soulignée du nombre. Par exemple, regardez le code ci-dessous:

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

Donc, si vous avez une méthode qui attend une chaîne de chiffres comme l'un des arguments, N'UTILISEZ PAS de soulignement pour séparer les chiffres car elle sera traitée comme n'importe quelle autre chaîne.

2
Willa