Après une discussion avec certains de mes collègues, j'ai une question «philosophique» sur la manière de traiter le type de données char en Java, en suivant les meilleures pratiques.
Supposons un scénario simple (bien entendu, ce n’est qu’un exemple très simple pour donner un sens à ma question) où, en prenant un String, vous devez compter le nombre de caractères numériques qu’il contient.
Ce sont les 2 solutions possibles:
1)
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) >= 48 && s.charAt(i) <= 57) {
n++;
}
}
2)
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) >= '0' && s.charAt(i) <= '9' ) {
n++;
}
}
Lequel des deux est le plus «propre» et conforme aux meilleures pratiques Java?
VK_
constantes que vous êtes censé utiliser, deuxièmement, utiliser des codes de caractères est meilleur que des caractères. @Brandin C'est ce qu'on appelle les pratiques de codageVK_*
constantes correspondent à des clés et non à des caractères .Réponses:
Les deux sont horribles, mais le premier est plus horrible.
Les deux ignorent la capacité intégrée de Java à décider quels caractères sont "numériques" (via les méthodes entrées
Character
). Mais la première ne tient pas compte non seulement la nature Unicode des chaînes, en supposant qu'il ne peut y avoir qu'une 0123456789, elle aussi obscurcit même ce raisonnement invalide en utilisant des codes de caractères qui font sens que si vous savez quelque chose sur l'histoire de codages de caractères.la source
matches("[0-9]+")
, plutôt que d'exploiter le tour de passe motivé par l'histoire.Ni. Laissez la classe de caractères intégrée de Java le découvrir pour vous.
Il y a un peu plus de plages de caractères que les chiffres ASCII qui comptent comme chiffres, et aucun exemple que vous avez posté ne les comptera. Le JavaDoc pour
Character.isDigit()
répertorie ces plages de caractères comme étant des chiffres valides:Cela étant dit, il convient de déléguer à
Character.isDigit()
même avec cette liste. Au fur et à mesure que les nouveaux plans Unicode sont remplis, le code Java sera mis à jour. La mise à niveau de la machine virtuelle Java pourrait permettre à l'ancien code de fonctionner de manière transparente avec les nouveaux caractères numériques. Il est également sec : en localisant le code «s’agit-il d’un chiffre» à un endroit référencé ailleurs, les aspects négatifs de la duplication de code (c.-à-d. Les bugs) peuvent être évités. Enfin, notez la dernière ligne: cette liste n’est pas exhaustive et il existe d’autres chiffres.Personnellement, je préférerais déléguer aux principales bibliothèques Java et consacrer mon temps à des tâches plus productives qu'à "déterminer ce qu'est un chiffre".
La seule exception à cette règle concerne les cas où vous devez réellement tester les chiffres ASCII littéraux et non les autres chiffres. Par exemple, si vous analysez un flux et que seuls les chiffres ASCII (par opposition aux autres chiffres) ont une signification particulière, il ne serait pas approprié de les utiliser
Character.isDigit()
.Dans ce cas, j’écrirais une autre méthode, par exemple,
MyClass.isAsciiDigit()
et jetterais la logique. Vous obtenez les mêmes avantages de la réutilisation du code, le nom est très clair quant à ce qu’il vérifie, et la logique est correcte.la source
Si vous écrivez une application en C qui utilise EBCDIC comme jeu de caractères de base et doit traiter des caractères ASCII, utilisez
48
et57
. Est-ce que tu fais ça? Je ne pense pas.À propos de l'utilisation
isDigit()
: cela dépend. Vous écrivez un analyseur JSON? Seulement0
pour9
sont acceptées sous forme de chiffres, ne l' utilisez pasisDigit()
, vérifiez>= '0'
et<= '9'
. Traitez-vous les entrées utilisateur? Utilisez-leisDigit()
tant que le reste de votre code peut gérer la chaîne et la transformer en nombre correctement.la source
Le deuxième exemple est clairement supérieur. La signification du deuxième exemple est immédiatement évidente lorsque vous regardez le code. La signification du premier exemple n’est évidente que si vous avez mémorisé l’intégralité de la table ASCII dans votre tête.
Vous devez faire la distinction entre rechercher un caractère spécifique ou rechercher une plage ou une classe de caractères.
1) Vérifier un caractère spécifique.
Pour les caractères ordinaires, utilisez le littéral de caractère, par exemple,
if(ch=='z')...
. Si vous comparez des caractères spéciaux tels que tabulation ou saut de ligne, vous devez utiliser les échappements, commeif (ch=='\n')...
. Si le caractère que vous recherchez est inhabituel (par exemple, non immédiatement reconnaissable ou indisponible sur un clavier standard), vous pouvez utiliser un code de caractère hexadécimal plutôt que le caractère littéral. Mais comme un code hexadécimal est une "valeur magique", vous devez l'extraire en une constante et la documenter:Les codes hexadécimaux constituent la méthode standard de spécification des codes de caractères.
2) Vérifier une classe de caractères ou une plage
Vous ne devriez vraiment pas faire cela directement dans le code de l'application, mais l'encapsuler dans une classe séparée uniquement concernée par la classification des caractères. Et vous devriez varier ce nombre, car des bibliothèques existent déjà à cet effet, et la classification des caractères est généralement plus complexe que vous ne le pensez, du moins si vous considérez des caractères en dehors de la plage ASCII.
Si vous ne vous souciez que des caractères de la plage ASCII, vous pouvez utiliser des littéraux de caractères dans cette bibliothèque, sinon vous utiliseriez probablement des littéraux hexadécimaux. Si vous examinez le code source de la bibliothèque de caractères intégrée Java, il fait également référence aux valeurs et aux plages de caractères utilisant hexadécimal, car elles sont spécifiées dans la norme Unicode.
la source
'\x2603'
indiquant plutôt que vous testez la valeur d'un caractère avec un codage hexadécimal et non pas n'importe quel nombre aléatoire.Il est toujours préférable d'utiliser
c >= '0'
car pourc >= 48
vous devez convertir c en code ASCII.la source
Les expressions régulières ( RegEx ) ont une classe de caractères spécifique pour les chiffres -
\d
- pouvant être utilisée pour supprimer tout autre caractère de votre chaîne. La longueur de la chaîne résultante est la valeur souhaitée.Notez, cependant, que les RegEx sont plus exigeants en calcul que les autres solutions proposées et qu’ils ne devraient donc pas être préférés .
la source