Après avoir vu comment formater des nombres et des dates afin de produire des messages adaptés à pas mal de situations, nous allons passer cette fois-ci un peu plus de temps sur le texte et sur tous les autres types de traitements qui s'y rattachent. Effectivement, la plupart des programmes manipulent du texte d'une manière ou d'une autre, aussi la plate-forme Java définit-elle un certain nombre de classes importantes pour représenter, formater, et parcourir du texte.
La représentation du texte se fait principalement au travers de la classe String que nous connaissons déjà. Nous allons toutefois y revenir pour décrire bien plus précisément l'ensemble des méthodes qui la constitue.
Toujours au travers de cette classe String, le formatage va nous permettre d'associer des variables d'une autre nature (des entiers, en hexadécimal ou pas, des réels, en représentation flottante ou pas, etc. ) avec une chaîne de caractères qui sert de canevas. A ce sujet, nous travaillerons également avec la classe Scanner qui réalise du formatage automatique avec des chaînes de caractères. Nous profiterons également de revoir tous les problèmes de conversion entre les chaînes de caractères avec les types primitifs, avec donc un retour sur les classes enveloppes, comme Integer, Double, etc.
Pour terminer sur cette introduction, nous avons souvent besoin d'analyser des textes afin de contrôler si un certain motif est respecter dans la chaîne de caractères. Nous allons donc travailler sur ce que nous appelons les expressions régulières qui gèrent des motifs correspondant à des critères d'évaluation.
Les chaînes de caractères correspondent à un type de données fondamental et couramment utilisé. En java, cependant, les chaînes de caractères ne correspondent pas à un type primitif, à la différence de char, int ou double. En lieu et place, les chaînes de caractères sont représentées par la classe java.lang.String qui définit de nombreuses méthodes pour la manipulation des chaînes de caractères. Les objets String sont immuables : une fois qu'un objet String a été créé, il n'existe aucune possibilité de modifier la chaîne de caractères qu'il représente. Ainsi, chaque méthode qui agit sur une chaîne de caractères retourne généralement un nouvel objet String qui contient la chaîne de caractères modifiée.
Un certain nombre de méthodes manipulent des objets String et renvoient un nouvel objet String comme résultat. Même si cela est utile, vous devez savoir qu'en créant beaucoup de chaînes de caractères de cette manière, les performances de l'application peuvent être affectées. Si vous désirez que votre application soit plus performante en proposant beaucoup de manipulation sur la même chaîne de caractères, préférez plutôt la classe StringBuilder que nous traiterons dans le prochain chapitre.
| java.lang.String | ||
|---|---|---|
| Méthodes | Retour | Explication |
| charAt(int index) | char | Récupère un caractère particulier dans la chaîne dont la position est précisée en argument. |
| codePointAt(int index) | int | Renvoie le point de code qui démarre ou se termine à l'emplacement spécifié. |
| codePointCount(int début, int fin) | int | Renvoie le nombre de points de code entre début et fin-1. Les substitutions sans paires sont considérées comme des points de code. |
| compareTo(String autreChaîne) compareToIgnoreCase(String autreChaîne) |
int | Compare la chaîne avec une autre chaîne passée en argument. Possibilité de ne pas tenir compte de la casse des caractères avec la deuxième méthode. |
| concat(String autreChaîne) | String | Concatène la chaine avec une autre. |
| endWith(String suffixe) | boolean | Vérifie si la chaîne de caractère se termine par le suffixe précisé en argument. |
| equals(String autreChaîne) equalsIgnoreCase(String autreChaîne) |
Object | Compare la chaîne à une autre en ne tenant pas compte de la casse des caractères éventuellement. |
| format(String format, Object ... args) | String | Méthode statique qui permet de formater un texte, en relations avec les arguments proposés, dans un motif défini à la manière de la fonction printf() du C++. |
| indexOf(String sousChaîne) indexOf(int car) indexOf(String sousChaîne, int décalage) indexOf(int car, int décalage) |
int | Cherche la première occurence d'un caractère ou d'une partie de la chaîne. |
| intern() | String | Cherche et renvoie une instance unique de la chaîne dans l'ensemble des chaînes partagées. |
| lastIndexOf(String sousChaîne) lastIndexOf(int car) lastIndexOf(String sousChaîne, int index) lastIndexOf(int car, int index) |
int | Cherche la dernière occurence d'un caractère ou d'une sous-chaîne. |
| length() | int | Renvoie la longueur de la chaîne. |
| match(String motif) | boolean | Evalue que la chaîne de caractères correspond au critère spécifié par le motif proposé exprimé sous la forme d'expression régulière. |
| offsetByteCodePoints(int début, int pointCode) | int | Renvoie l'indice du point de code d'où pointe pointCode, depuis le point de code jusqu'à début. |
| replace(char ancien, char nouveau) | String | Remplace toutes les occurences d'un caractère dans une chaîne par un autre caractère. |
| replaceAll(String motif, String remplacement) replaceFirst(String motif, String remplacement) |
String | Remplace toutes les occurences ou la première partie de la chaîne de caractère avec la chaîne de remplacement spécifiée en argument à partir d'un motif défini par une expression régulière. |
| split(String motif) | String[] | Décompose la chaîne en un tableau de chaînes en utilisant comme séparateur un élément d'expression régulière. |
| startWith(String prefixe) | boolean | Vérifie si la chaîne débute par un prefixe. |
| subString(int début) subString(int début, int fin) |
String | Retourne une partie de la chaîne. Attention, le caractère indicé par début est pris en compte, alors que le caractère correspondant à fin ne l'est pas ; fin représente la limite supérieure exclusive. |
| toLowerCase() | String | Convertit la chaîne en minuscule. |
| toUpperCase() | String | Convertit la chaîne en majuscule. |
| trim() | String | Supprime les espaces blancs de début et de fin de chaîne. |
| valueOf(Type valeur) | String | Renvoie une chaîne de caractères correspondant à la valeur numérique passée en paramètre de la méthode. Type = int, long, double, float, Object, char[], char, boolean. |
Dans ce chapitre, nous allons nous consacrer uniquement sur les méthodes de bases. Nous verrons par la suite comment travailler avec les valeurs numériques, comment formater de telles valeurs, comment récupérer des valeurs quelconques à partir de la classe Scanner, et surtout comment travailler avec les expressions régulières, puisqu'il s'agit d'un sujet important. Tous ces autres points seront, bien entendus traités, mais dans les prochains chapitres.
Si vous désirez créer un objet String à partir d'un message spécifique, il suffit de placer ce dernier entre guillemets. Lorsque vous déclarez un objet de type String sans préciser de valeur, votre objet n'est pas initialisé. Il faudra le faire par la suite. Rappelez-vous d'ailleurs que comme tout autre objet, le nom de l'objet correspond en réalité à un pointeur vers l'objet réel où sont placées toutes ses valeurs internes. Pour terminer, un texte exprimé entre guillemets dans votre code est finalement considéré comme un objet de type String.
String message = "Mon texte personnel"; // déclaration et initialisation de l'objet message String texte; // déclaration de l'objet texte sans être initialisé System.out.println(texte); // erreur de compilation texte = "Autre message"; // initialisation de l'objet texte System.out.println(message); // affichage de message System.out.println(texte); // affichage de texte
Comme toujours, les tableaux Java étant de vrais objets qui connaissent leur propre taille, les objets String n'ont pas besoin de caractère de terminaison. Pour connaître la taille d'un objet String, utilisez pour cela sa méthode length().
String message = "Mon texte personnel"; int longueur = message.length(); // longueur = 19 longueur = "Autre message".length(); // longueur = 13
La chaîne de caractères représentées par le texte entre guillemets, comme nous l'avons dit plus haut, est considéré comme un objet de type String. A ce titre, vous avez donc le droit de solliciter toutes les méthodes que vous désirez à partir de ce texte, comme ici avec la méthode length().
Il est possible de juxtaposer plusieurs chaînes, les unes à la suite des autres, ce que nous appelons une concaténation de chaînes. Il existe la méthode concat() qui réalise ce type d'opération. Egalement, l'opérateur + a été redéfini pour concaténer deux objets String ou un objet String avec une valeur d'un autre type, produisant en sortie un nouvel objet String. Pour finir, nous pouvons également travailler avec l'opérateur += pour concaténer deux chaînes. Dans ce cas là, le contenu de la première chaîne est modifié.
public class Principal { public static void main(String[] args) { String message = " le moment"; String texte = "C'est".concat(message); String s = texte +" d'intégrer le nombre réel "+12.89; s += " dans ce message"; String autre = "C'est"+message.concat(" d'intégrer le nombre réel ")+12.89; System.out.println(s); System.out.println(autre); } }
C'est le moment d'intégrer le nombre réel 12.89 dans ce message
C'est le moment d'intégrer le nombre réel 12.89
Soyez conscient que chaque fois qu'une concaténation de chaînes de caractères est réalisée et que le résultat est enregistré dans une variable ou passé à une méthode, un nouvel objet String doit être créé. Dans certaines circonstances, cela peut s'avérer très peu efficace et dégrader les performances.
Les chaînes littérales (entre guillemets) ne peuvent occuper plusieurs lignes sur le code source, mais il est possible de les concaténer pour obtenir le même résultat :
String grandMessage = "Voici un grand message qui doit " + "s'écrire sur plusieurs lignes. Je suis obligé d'utiliser " + "l'opérateur + pour cela";
La méthode charAt() de la classe String permet de récupérer un seul caractère de la chaîne. Vous devez spécifier sa position dans la chaîne au travers du paramètre de la méthode :
S
a
l
u
t
public class Principal { public static void main(String[] args) { String bonjour = "Salut"; for (int i=0; i<bonjour.length(); i++) System.out.println(bonjour.charAt(i)); } }
La classe String propose plusieurs méthodes simples permettant de retrouver des parties de la chaîne. Les méthodes startsWith() et endsWith() comparent un argument avec le début et la fin de la chaîne. Il est possible de récupérer une partie de la chaîne à l'aide de la méthode substring(). Par contre, cette méthode réclame, d'une part où débute la sous-chaîne et d'autre part où elle se termine, ceci au travers d'indices numériques que vous spécifiez dans les arguments. A propos d'indice, il est possible également de délivrer l'emplacement d'un caractère ou d'une partie de la chaîne à partir de la méthode indexOf(). Cette méthode recherche la première occurence. Par contre, la méthode lastIndexOf() fait la même chose, mais à partir de la dernière occurence.
Nom du site : unsite
public class Principal { public static void main(String[] args) { String url = "http://www.unsite.fr/"; if (url.startsWith("http://") && url.endsWith("fr/")) { int début = url.indexOf('.')+1; int fin = url.lastIndexOf("."); String site = "Nom du site : "+ url.substring(début, fin); System.out.println(site); } } }
La méthode trim() est très utile pour supprimer tous les espaces blancs aux deux extrémités d'une chaîne de caractères (c'est-à-dire les caractères retour chariot, nouvelle ligne, tabulation et tout simplement les espaces). Par ailleurs, les méthodes toUpperCase() et toLowerCase() renvoient un nouvel objet String qui est, soit tout en majuscules, soit tout en minuscules.
En majuscules : BONJOUR À TOUT LE MONDE
En minuscules : bonjour à tout le monde
public class Principal { public static void main(String[] args) { String bienvenue = " Bonjour à tout le monde "; bienvenue = bienvenue.trim(); System.out.println("En majuscules : "+bienvenue.toUpperCase()); System.out.println("En minuscules : "+bienvenue.toLowerCase()); } }
Puisque les chaînes de caractères sont des objets plutôt que des valeurs primitives, elles ne peuvent généralement pas être comparées directement avec l'opérateur d'égalité ==. Si nous le faisons, == compare des références et peut déterminer si deux expressions pointent vers une même référence de chaîne de caractères. Par contre, cet opérateur d'égalité ne peut pas déterminer si deux chaînes de caractères distinctes contiennent le même texte.
Bonjour
false
import java.util.Scanner; public class Principal { public static void main(String[] args) { Scanner clavier = new Scanner(System.in); String message = "Bonjour"; String saisie = clavier.next(); System.out.println(message==saisie); } }
Pour tester l'égalité de deux chaînes de caractères, utilisez plutôt la méthode equals(). Il est possible également d'utiliser la méthode equalsIgnoreCase() en lieu et place de la méthode equals() si vous désirez ne pas tenir compte de la casse des caractères.
Bonjour
true
true
import java.util.Scanner; public class Principal { public static void main(String[] args) { Scanner clavier = new Scanner(System.in); String message = "Bonjour"; String saisie = clavier.next(); System.out.println(message.equals(saisie)); System.out.println("BONJOUR".equalsIgnoreCase(saisie)); } }
Bien que méconnue, intern() est une méthode importante de la classe String. Cette méthode retourne une nouvelle chaîne de caractères avec la garantie que la nouvelle chaîne possède le même contenu. En réalité, intern() retourne toujours une référence vers le même objet String. Autrement dit, si s et t sont deux objets String tels que s.equals(t), alors :
s.intern() == t.intern()
Cela signifie que la méthode intern() permet de réaliser des comparaisons de chaînes rapides en utilisant ==. Plus important encore, les littéraux chaînes sont toujours internés par la JVM Java de façon implicites, de sorte que si vous prévoyez de comparer une chaîne s avec un certain nombre de littéraux de chaînes, vous devriez interner s puis effectuer la comparaison avec ==.
Bonjour
true
true
true
false
import java.util.Scanner; public class Principal { public static void main(String[] args) { Scanner clavier = new Scanner(System.in); String message = "Bonjour"; String bienvenue = "Bonjour"; String saisie = clavier.next(); System.out.println(message==bienvenue); System.out.println("Bonjour"==bienvenue); System.out.println(message.equals(saisie)); System.out.println(saisie=="Bonjour"); } }
La méthode compareTo() permet de comparer la valeur lexicale d'un String à un autre String. Elle renvoie un entier strictement inférieur, égal ou strictement supérieur à 0. compareToIgnoreCase() fait la même chose, mais sans tenir compte de la casse des caractères.
true
true
true
public class Principal { public static void main(String[] args) { String abc = "abc"; String def = "def"; String num = "123"; System.out.println(abc.compareTo(def)<0); System.out.println(abc.compareTo("abc")==0); System.out.println(abc.compareTo(num)>0); } }
Les chaînes Java sont implémentées sous forme de suites de valeurs char. Comme nous l'avons vu, le type char est une unité de code permettant de représenter des points de code Unicode en codage UTF-16. Les caractères Unicode les plus souvent utilisés peuvent être représentés par une seule unité de code. Les caractères complémentaires exigent, quant à eux, une paire d'unité de code.
String chaîne = "Bonjour";
int longueur = chaîne.length(); // longueur vaut 7
int pointsCode = chaîne.codePointCount(0, chaîne.length());
char premier = chaîne.charAt(0); // le premier est 'B'
char dernier = chaîne.charAt(6); // le premier est 'r'
int index = chaîne.offsetByCodePoints(0, n);
int dernier = chaîne.codePointAt(index);
Etant donné que les objets String sont immuables, vous ne pouvez pas manipuler les caractères d'un objet String de manière directe. Si vous avez besoin d'objets modifiables, utilisez plutôt java.lang.StringBuilder.
| java.lang.StringBuilder | ||
|---|---|---|
| Méthodes | Retour | Explication |
| append(...) | StringBuilder | Ajoute à la chaîne déjà existante une autre chaîne, un caractère, une valeur numérique, un objet, etc. |
| charAt(int index) | char | Récupère un caractère particulier dans la chaîne dont la position est précisée en argument. |
| delete(int début, int fin) |
StringBuider | Enlève les caractères de la chaîne dans la limite spécifiée en argument. |
| deleteCharAt(int index) | StringBuilder | Enlève un seul caractère. |
| indexOf(String sousChaîne) indexOf(String sousChaîne, int décalage) |
int | Cherche la première occurence d'une partie de la chaîne. |
| insert(int index, ...) | StringBuilder | Insère à la chaîne déjà existante une autre chaîne, un caractère, une valeur numérique, un objet, etc. à l'emplacement spécifié par index. |
| lastIndexOf(String sousChaîne) lastIndexOf(String sousChaîne, int index) |
int | Cherche la dernière occurence d'une partie de la chaîne. |
| length() | int | Renvoie la longueur de la chaîne. |
| replace(int début, int fin, String nouvelle) | StringBuilder | Remplace une partie de la chaîne |
| reverse() |
StringBuilder | Inverse la chaîne. |
| setCharAt(int index, char ch) | Remplace dans la chaîne le caractère spécifié par rapport à l'indice proposé. | |
| setLenght(int taille) | Impose une nouvelle taille de la chaîne. | |
| subString(int début) subString(int début, int fin) |
String | Retourne une partie de la chaîne. Attention, le caractère indicé par début est pris en compte, alors que le caractère correspondant à fin ne l'est pas ; fin représente la limite supérieure exclusive. |
| toString() | String | Récupération de la chaîne de caractère en format String. |
public class Principal { public static void main(String[] args) { StringBuilder b = new StringBuilder("N'est"); // Création du tampon de chaîne avec la valeur "N'est" char car = b.charAt(0); // Retourne N b.setCharAt(0, 'C'); // changer un caractère : "C'est" : on ne peut pas faire cela avec un objet String b.append(' '); // ajoute un espace à la fin de la chaîne "C'est " b.append("Le moment."); // ajoute une chaine à la fin "C'est le moment." b.append(23); // ajoute un entier ou une valeur quelconque "C'est le moment.23" b.insert(6, "pas "); // insère une chaîne de caractère "C'est pas le moment.23" b.replace(2, 9, "est "); // remplace une partie de la chaîne "C'est le moment.23" b.delete(15, 18); // supprime une partie de la chaîne "C'est le moment" b.deleteCharAt(2); // supprime le troisème caractère "C'st le moment" b.setLength(5); // Tronque la chaîne pour aboutir à la taille désirée "C'st " b.reverse(); // Inverse les caractères " ts'C" String s = b.substring(1, 2); // extrait une partie de chaîne "t" s = b.toString(); // reconversion vers une chaîne immuable. System.out.println(s); System.out.println(b); // fait automatiquement appel à la méthode toString() de StringBuilder b.setLength(0); // écrase le tampon ; il est désormais prêt à être réutilisé } }
ts'C
ts'C
Comme vous le savez, les caractères individuels sont représentés en Java par le type primitif char. La plate-forme Java possède également une classe Character qui définit des méthodes de classe pour contrôler le type d'un caractère ou pour modifier la casse d'un caractère.
| java.lang.Character | ||
|---|---|---|
| Méthodes | Retour | Explication |
| static getNumericValue(char ch) | int | Retourne la valeur entière correspondante au chiffre exprimé dans le caractère. Prend donc en compte uniquement les caractères suivants : de '0' à '9'. |
| static isDigit(char ch) | boolean | Teste si le caractère représente un chiffre. |
| static isLetter(char ch) | boolean | Teste si le caractère représente une lettre. |
| static isLetterOrDigit(char ch) | boolean | Teste si le caractère représente une lettre ou un chiffre (pas de symbole de ponctuation). |
| static isLowerCase(char ch) | boolean | Teste si le caractère est en minuscule. |
| static isSpaceChar(char ch) | boolean | Teste si le caractère est le caractère espace. |
| static isUpperCase(char ch) | boolean | Teste si le caractère est en majuscule. |
| static isWhiteSpace(char ch) | String | Cherche et renvoie une instance unique de la chaîne dans l'ensemble des chaînes partagées. |
| static toLowerCase(char ch) | int | Renvoie le caractère en minuscule. |
| static toUpperCase(char ch) | int | Renvoie le caractère en majuscule. |
public class Principal { public static void main(String[] args) { char lettre = 'A'; char chiffre = '7'; char accent = 'é'; char espace = ' '; char blanc = '\n'; System.out.println(Character.getNumericValue(chiffre)); // 7 System.out.println(Character.isDigit(lettre)); // false System.out.println(Character.isDigit(chiffre)); // true System.out.println(Character.isLetter(lettre)); // true System.out.println(Character.isLetter(chiffre)); // false System.out.println(Character.isLetter(accent)); // true System.out.println(Character.isLetterOrDigit(chiffre)); // true System.out.println(Character.isLowerCase(lettre)); // false System.out.println(Character.isSpaceChar(lettre)); // false System.out.println(Character.isSpaceChar(espace)); // true System.out.println(Character.isUpperCase(lettre)); // true System.out.println(Character.isWhitespace(lettre)); // false System.out.println(Character.isWhitespace(blanc)); // true } }
Il est parfois nécessaire de convertir un type primitif - comme int - en un objet. Tous les types primitifs ont une contrepartie sous forme de classe. Par exemple, il existe une classe Integer correspondant au type primitif int. Une classe de cette catégorie est généralement appelée classe enveloppe (object wrapper). Les classes enveloppes portent des noms correspondant aux types : Integer, Long, Float, Short, Byte, Character, Void et Boolean (les six premières héritent de la super classe Number). Les classes enveloppes sont inaltérables : vous ne pouvez pas modifier une valeur enveloppée, une fois l'enveloppe construite. Elles sont aussi final, vous ne pouvez donc pas en faire des sous-classes.
Supposons que nous voulions travailler sur une liste d'entiers. Nous pensons, tout de suite, utiliser la collection ArrayList<int>. Malheureusement, le paramètre de type entre les signes <> ne peut pas être un type primitif, c'est obligatoirement un objet. C'est à ce niveau là que la classe enveloppe devient intéressante. Vous pouvez ainsi déclarer une liste de tableau d'objet Integer :
ArrayList<Integer> liste = new ArrayList<Integer>() ;
Attention : un ArrayList<Integer> est bien moins efficace qu'un tableau int[] car chaque valeur est enveloppée séparément dans un objet. Vous ne devriez utiliser cette construction que pour les petites collections lorsque la commodité du programmeur est plus importante que l'efficacité.
Une autre innovation du JDK 5.0 facilite l'ajout et la récupération d'éléments de tableau. L'appel :
liste.add(3);
est automatiquement traduit en :
liste.add(new Integer(3));
Cette conversion est appelée autoboxing.
A l'inverse, lorsque vous attribuez un objet Integer à une valeur int, il est automatiquement déballé (unboxing). En fait, le compilateur traduit :
int n = liste.get(i) ;
en
int n = liste.get(i).intValue() ;
Les opérations d'autoboxing et d'unboxing fonctionne même avec les expressions arithmétiques. Vous pouvez, par exemple, appliquer l'opération d'incrémentation en une référence d'enveloppe :
Integer n = 3;
n++ ;
Le compilateur insère automatiquement des instructions pour déballer l'objet, augmenter la valeur du résultat et le remballer.
Dans la plupart des cas, vous avez l'illusion que les types primitifs et leurs enveloppes ne sont qu'un seul et même élément. Ils ne diffèrent considérablement qu'en un seul point : l'identité.
Vous verrez souvent les enveloppes de nombres pour une autre raison. Les concepteurs Java ont découvert que les enveloppes constituent un endroit pratique pour y stocker certaines méthodes de base, comme celles qui permettent de convertir des chaînes de chiffres en nombres.
Pour transformer une chaîne en entier, vous devez utiliser l'instruction suivante :
int x = Integer.parseInt(s) ;
Ceci n'a rien à voir avec les objets Integer ; parseInt() est une méthode statique. Mais la classe Integer constitue un bon endroit pour l'y placer. Pour transformer un entier en une chaîne représentant la suite des chiffres du nombre entier, utilisez la méthode toString() :
String chiffres = Integer.toString(324) ; // chiffres <-- "324"
Voici un exemple :
| Test.java |
|---|
package test; import java.util.Scanner; import static java.lang.System.*; public class Test { public static void main(String[] args) { Scanner clavier = new Scanner(in); out.print("Introduisez votre nombre entier : "); String chaîne = clavier.next(); Integer X = new Integer(chaîne) ; int x = X; // ou plus rapidement : int x = clavier.nextInt(); out.println("Valeur entière : "+x); out.println("Chaîne de caractère équivalente : "+X); // équivalent à Integer.toString(x); out.println("Valeur binaire correspondante : "+Integer.toBinaryString(x)); } } |
Vous avez ci-dessous, les tableaux montrant toutes les méthodes utiles sur les entiers et les réels dont les deux classes enveloppes Integer et Double sont les principales représentantes.
| java.lang.Integer | ||
|---|---|---|
| Attributs | ||
| static final int MAX_VALUE | Valeur maximale que peut représenter un nombre entier : 231-1. | |
| static final int MIN_VALUE | Valeur minimale que peut représenter un nombre entier : -231. | |
| Méthodes | ||
| Integer(int valeur) | Construit la classe enveloppe correspondante à partir de l'entier passé en argument. | |
| Integer(String valeur) | Construit la classe enveloppe correspondante à partir d'une chaîne de caractères représentant la suite des chiffres du nombre entier. | |
| static int bitcount(int valeur) | Retourne le nombre de bit à 1 dans la représentation binaire en complément à deux de la valeur entière spécifiée en argument de la méthode. | |
| int compareTo(Integer autre) | Compare la valeur numérique entre deux objets de type Integer. Si la valeur retournée est positive, cela signifie que la valeur numérique de l'objet est supérieur à la valeur numérique de l'objet passé en argument. Une valeur négative est retournée dans le cas contraire. Enfin, si les deux objets possèdent la même valeur numérique, c'est la valeur nulle qui est renvoyée. | |
| static Integer decode(String valeur) | Méthode statique qui renvoie un objet de type Integer qui enveloppe la valeur numérique représentée par la suite des chiffres spécifiés dans la chaîne de caractères. Cette méthode gère les représentations octale, décimale ou hexadécimale suivant le préfixe numérique de la chaîne de caractères. |
|
| static int highestOneBit(int valeur) | Méthode statique qui renvoie la valeur entière correspondante au bit 1 le plus à gauche, dans la représentation binaire du nombre entier passé en argument. | |
| static int lowestOneBit(int valeur) | Méthode statique qui renvoie la valeur entière correspondante au bit 1 le plus à droite, dans la représentation binaire du nombre entier passé en argument. | |
| static int numberOfLeadingZeros(int valeur) | Retourne le nombre de zéro, en partant de la gauche, dans la représentation binaire en complément à deux de la valeur entière spécifiée en argument. | |
| static int numberOfTrailingZeros(int valeur) | Retourne le nombre de zéro, en partant de la droite, dans la représentation binaire en complément à deux de la valeur entière spécifiée en argument. | |
| static int parseInt(String valeur) static int parseInt(String valeur, int base) |
Méthode statique qui retourne une valeur entière représentée par la suite des chiffres spécifiés dans la chaîne de caractères donnée en argument. Vous pouvez également précisez une autre base que la base 10. La valeur numérique retournée est en base 10. Elle est alors convertie à partir de la chaîne proposée, exprimée dans la base souhaitée. | |
| static int reverse(int valeur) | Méthode statique qui retourne une valeur entière dont l'ordre des bits est inversé par rapport à l'entier passé en argument. | |
| static int rotateLeft(int valeur, int nombre ) | Méthode statique qui retourne un entier qui a subit une rotation vers la gauche de l'entier valeur de nombre de position. | |
| static int rotateRight(int valeur, int nombre ) | Méthode statique qui retourne un entier qui a subit une rotation vers la droite de l'entier valeur de nombre de position. | |
| static int signum(int valeur) | Renvoie le signe de l'entier sous la forme -1, 0, 1. | |
| static String toBinaryString(int valeur) | Méthode statique qui retourne une chaîne de caractères qui représente une valeur entière en format binaire d'un nombre entier passé en argument. | |
| static String toHexString(int valeur) | Méthode statique qui retourne une chaîne de caractères qui représente une valeur entière en format hexadécimal d'un nombre entier passé en argument. | |
| static String toOctalString(int valeur) | Méthode statique qui retourne une chaîne de caractères qui représente une valeur entière en format octal d'un nombre entier passé en argument. | |
| String toString() | Méthode qui retourne une chaîne de caractère qui est une représentation du nombre entier de l'objet. | |
| static String toString(int valeur, int base) | Méthode statique qui retourne une chaîne de caractères qui représente une valeur entière dont la base est déterminé par base du nombre entier valeur passé en argument. | |
| static Integer valueOf(int valeur) | Méthode statique qui retourne un objet de type Integer correspondant à la valeur entière passée en argument. | |
| static Integer valueOf(String valeur) | Méthode statique qui retourne un objet de type Integer correspondant à la chaîne de caractères passée en argument qui représente une valeur entière. | |
| static Integer valueOf(String valeur, int base) | Même méthode que précédemment. Toutefois, le nombre est représenté dans une base quelconque qu'il s'agit de spécifier au moyen de l'argument base. | |
| java.lang.Double | ||
|---|---|---|
| Attributs | ||
| static final int MAX_VALUE | Valeur maximale que peut représenter un nombre réel : 1.7976931348623157 E308. | |
| static final int MIN_VALUE | Valeur minimale que peut représenter un nombre entier : 4.9 E-324. | |
| static final int NaN | Correspond à une valeur spéciale du type double ne représentant pas un nombre (Not a Number). | |
| static final int POSITIVE_INFINITY | Infini positif. | |
| static final int NEGATIVE_INFINITY | Infini négatif. | |
| Méthodes | ||
| Double(double valeur) | Construit la classe enveloppe correspondante à partir du réel passé en argument. | |
| Double(String valeur) | Construit la classe enveloppe correspondante à partir d'une chaîne de caractères représentant la suite des chiffres du nombre réel. | |
| static int compare(double un, double deux) | Compare la valeur numérique entre deux objets de type double. | |
| static boolean isInfinite(double valeur) | Détermine si la valeur réelle passée en argument est une valeur infinie. | |
| static double parseDouble(String valeur) | Méthode statique qui retourne une valeur réelle représentée par la suite des chiffres spécifiés dans la chaîne de caractères donnée en argument. | |
| static Double valueOf(double valeur) | Méthode statique qui retourne un objet de type Double correspondant à la valeur réelle passée en argument. | |
| static Double valueOf(String valeur) | Méthode statique qui retourne un objet de type Double correspondant à la chaîne de caractères passée en argument qui représente une valeur réelle. | |
public class Principal { public static void main(String[] args) { int nombre = 44; System.out.println("Représentation binaire : "+Integer.toBinaryString(nombre)); System.out.println("Nombre de bit à 1 : "+Integer.bitCount(nombre)); System.out.println("Valeur décimale du bit 1 le plus fort : "+Integer.highestOneBit(nombre)); System.out.println("Valeur décimale du bit 1 le plus faible : "+Integer.lowestOneBit(nombre)); System.out.println("Nombre de bit 0 en partant de la gauche : "+Integer.numberOfLeadingZeros(nombre)); System.out.println("Nombre de bit 0 en partant de la droite : "+Integer.numberOfTrailingZeros(nombre)); System.out.println("Symétrie horizontale du nombre binaire : "+Integer.toBinaryString(Integer.reverse(nombre))); System.out.println("Décalage vers la gauche de 2 unités : "+Integer.toBinaryString(Integer.rotateLeft(nombre, 2))); System.out.println("Représentation hexadécimale : "+Integer.toHexString(nombre)); System.out.println("Représentation octale : "+Integer.toOctalString(nombre)); System.out.println("Signe : "+Integer.signum(nombre)); System.out.println("Valeur décimale du nombre binaire 1101 : "+Integer.valueOf("1101", 2)); } }
Représentation binaire : 101100
Nombre de bit à 1 : 3
Valeur décimale du bit 1 le plus fort : 32
Valeur décimale du bit 1 le plus faible : 4
Nombre de bit 0 en partant de la gauche : 26
Nombre de bit 0 en partant de la droite : 2
Symétrie horizontale du nombre binaire : 110100000000000000000000000000
Décalage vers la gauche de 2 unités : 10110000
Représentation hexadécimale : 2c
Représentation octale : 54
Signe : 1
Valeur décimale du nombre binaire 1101 : 13
if (x == Double.NaN) // n'est jamais vrai
Toutes les valeurs "pas un nombre" sont considérées comme distinctes. Pour cela vous devez employer la méthode isNaN() de la classe enveloppe Double pour réaliser ce genre de test :
if (Double.isNaN(x)) // vérifier si x est "pas un nombre"
Attention : Les nombres à virgule flottante ne conviennent pas aux calculs financiers, dans lesquels les erreurs d'arrondi sont inadmissibles. La commande System.out.println(2.0-1.1) produit 0.899999999999999, et non 0.9 comme vous pourriez le penser. Ces erreurs d'arrondi proviennent u fait que les nombres à virgule flottante sont représentés dans un système de nombres binaires. Il n'existe pas de représentation binaire précise de la fraction 1/10, tout comme il n'existe pas de représentation précise de la fraction 1/3 dans un système décimal. Si vous voulez obtenir des calculs numériques précis sans erreurs d'arrondi, utilisez la classe BigDecimal.
Dans le développement d'applications, nous sommes souvent confrontés devant deux genres de situations classiques. Tout d'abord, nous avons besoin de récupérer une valeur numérique à partir d'une chaîne de caractères saisie au clavier ou venant d'un flux quelconque. Ainsi, une fois que nous avons récupérée la valeur, nous pouvons librement réaliser tous les traitements souhaitables. Ensuite, nous devons souvent afficher ce résultat numérique en association avec du texte.
Ce chapitre va nous aider à y voir plus clair sur ce sujet, sans être toutefois exhaustif puisque les chapitres suivants vont nous aider à aller encore plus loin dans ce domaine.
Comment un programme Java qui agit sur les nombres reçoit-t-il ses valeurs d'entrée ? Souvent, un tel programme lit une représentation textuelle d'un nombre et doit la convertir en une représentation numérique. Comme nous venons juste de la voir dans le chapitre précédent, les diverses sous-classes de Number : Integer, Double, Boolean, etc. définissent des méthodes de conversion très utiles :
public class Principal { public static void main(String[] args) { String s = "-42"; byte b = Byte.parseByte(s); // s sous forme d'octet short sh = Short.parseShort(s); // s sous forme de valeur int i = Integer.parseInt(s); // s sous forme de valeur long l = Long.parseLong(s); // s sous forme de valeur float f = Float.parseFloat(s); // s sous forme de valeur double d = Double.parseDouble(s); // s sous forme de valeur // les routines de conversion entière gère les nombres en diverses bases b = Byte.parseByte("1011", 2); // 1011 en binaire donne b=11 en base 10 sh = Short.parseShort("ff", 16); // ff en base 16 donne sh=255 en base 10 // la méthode valueOf() peut gérer les bases arbitraires i = Integer.valueOf("egg", 17); // Base 17 // la méthode decode() gère les représentation octale, décimale ou // hexadécimale suivant le préfixe numérique de la chaîne de caractères sh = Short.decode("0377"); // un 0 de tête signifie base 8 i = Integer.decode("0xff"); // un 0x de tête signifie base 16 l = Long.decode("255"); // Les autres nombres sont en base 10 } }
double valeur = Double.parseDouble("1 234,56"); // erreur lors de l'analyse du nombre exprimé dans la chaîne de caractères.
Si vous devez travailler avec ce type d'écriture, revoyez l'étude précédente qui nous a montré comment gérer les formats des nombres au niveau international, ou alors consultez les chapitres suivants.Toujours en se servant de ces classes enveloppes, vous avez la possibilité de passer cette fois-ci d'une valeur primitive vers la chaîne de caractères correspondante. Vous pouvez même envisager de contrôler la base du nombre et ainsi d'avoir une représentation très sophistiquée dans la chaîne de caractères :
int nombre = 42; String décimal = Integer.toString(nombre); String binaire = Integer.toBinaryString(nombre); String octal = Integer.toOctalString(nombre); String hexadécimal = Integer.toHexString(nombre); String base36 = Integer.toString(nombre, 36); hexadécimal = Integer.toHexString(nombre).toUpperCase();
Il est possible d'obtenir une représentation sous forme de chaîne de caractères de la plupart des types, grâce à la méthode statique valueOf() de la classe String. Plusieurs versions surchargées de cette méthode donnent des valeurs pour tous les types de base :
String un = String.valueOf(1); String deux = String.valueOf(2.384f); String pasVrai = String.valueOf(false);
Tous les objets Java possèdent une méthode toString() héritée de la classe Object. Pour des références de type classe, valueOf() appelle en réalité la méthode toString() de l'objet pour récupérer sa représentation sous forme de chaîne. Si la référence est égale à null, le résultat est une chaîne "null".
import java.util.Date; public class Principal { public static void main(String[] args) { String aujourdhui = String.valueOf(new Date()); System.out.println("La date d'aujourd'hui est "+aujourdhui); } }
La date d'aujourd'hui est Mon Mar 12 09:52:35 CET 2007
La représentation de la date n'est pas terrible. Encore une fois, reportez-vous sur l'étude précédente pour avoir un formatage de la date qui respecte vos désirs, ou alors consultez les chapîtres suivants.
import java.util.Date; public class Principal { public static void main(String[] args) { // récupérer la chaîne de caractères équivalente et afficher String un = ""+1; String deux = ""+2.384f; String aujourdhui = ""+new Date(); System.out.println(un); System.out.println(deux); System.out.println("La date d'aujourd'hui est "+aujourdhui); // alternatives beaucoup plus souvent utilisées -> Affichage direct System.out.println("Valeur entière : "+1); System.out.println("Valeur réelle : "+2.384f); System.out.println("La date d'aujourd'hui est "+new Date()); } }
1
2.384
La date d'aujourd'hui est Mon Mar 12 10:11:16 CET 2007
Valeur entière : 1
Valeur réelle : 2.384
La date d'aujourd'hui est Mon Mar 12 10:11:16 CET 2007
Une tâche courante lorsque nous travaillons avec du texte en sortie consiste à combiner les valeurs de divers types en un unique bloc de texte lisible par un être humain. Comme nous venons de le découvrir dans le chapitre précédent, une manière d'accomplir cette tâche se base sur les aptitudes de l'opérateur Java de concaténation de chaînes. Cela produit du code ressemblant à ceci :
String utilisateur = "Emmanuel REMY"; int essais = 15; Date date = new Date(); ... System.out.println(utilisateur+" connecté après "+essais+" essais. Dernière connexion le "+date);
Emmanuel REMY connecté après 15 essais. Dernière connexion le lun. mars 12 14:09:45 CET 2007
Depuis Java 5.0, il existe maintenant une alternative plus familière pour les programmeurs C : une méthode printf(). printf est l'abbrévation de print formatted, c'est-à-dire impression formatée, et combine des fonctions d'impression et de formatage en un seul appel. La méthode printf() a été rajoutée aux classes de flux de sortie PrintWriter et PrintStream. Il s'agit d'une méthode qui attend un nombre variable d'arguments. Le premier argument est la chaîne de formatage. Cette dernière spécifie le texte à afficher et inclut typiquement un ou plusieurs spécificateurs de format sous forme de séquences d'échappement commençant par le caractère %. Les arguments restants de printf() sont des valeurs à convertir en chaînes et à substituer aux spécificateurs de format dans la chaîne de formatage. Les spécificateurs de format influencent les types des arguments restants et spécifient de manière exacte comment ils doivent être convertis en chaînes.
La concaténation de chaînes illustrée ci-dessus peut être réécrite de la manière suivante :
String utilisateur = "Emmanuel REMY"; int essais = 15; Date date = new Date(); ... System.out.printf("%s connecté après %d essais. Dernière connexion le %tc%n", utilisateur, essais, date);
Au spécificateur de format %s se substitue simplement une chaîne de caractères. %d indique que l'argument doit être entier. %tc attend un objet Date, Calendar ou un nombre en millisecondes et convertit cette valeur en une représentation textuelle de la date et de l'heure. %n ne réalise aucune conversion : il produit simplement une terminaison de ligne spécifique à la plate-forme, tout comme la méthode println().
Les conversions réalisées par printf() sont toutes proprement localisées. Ainsi, les heures et les dates sont affichées avec une ponctuation adaptée aux paramètres de localisation. De même, si vous souhaitez qu'un nombre soit affiché avec un séparateur de milliers, la ponctuation sera également spécifique aux paramètres de localisation (un espace en France, une virgule aux USA, etc).
Outre la méthode printf() de base, les classes PrintWriter et PrintStream définissent aussi une méthode synonyme nommée format() : elle accepte exactement les mêmes arguments et se comporte de la même manière. La classe String possède également une méthode format(). Cette méthode statique String.format() se comporte comme la méthode PrintWriter.format(), à la différence près qu'elle retourne la chaîne de caractères plutôt que de l'envoyer dans un flux.
Chaque spécificateur de format commence donc par un signe pourcentage et se termine par un type de conversion d'un ou de deux caractères, lequel spécifie la plupart des détails relatifs à la conversion et à l'affichage. Entre ces deux éléments se trouvent les drapeaux facultatifs qui fournissent d'autres détails de formatage. La syntaxe générale d'un spécificateur de format est la suivante. Les parenthèses carrées indiquent les éléments facultatifs :
%[argument][drapeaux][largeur][.précision]type
Nous allons décrire chacun des éléments qui composent le spécificateur de format. Nous commençons tout d'abord par le type.
| type de Conversion | ||
|---|---|---|
| d | Formate l'argument sous forme d'entier en base 10. L'argument doit être d'un type entier compatible | 159 |
| x, X | Formate l'argument sous forme d'entier en base 16 (hexadécimal). Représentation en majuscule pour le type X. | 9F |
| o | Formate l'argument sous forme d'entier en base 8 (octal). | 237 |
| f | Formate l'argument sous forme de nombre à virgule flottante en base 10, sans utiliser la notation exponentielle. | 15.9 |
| e, E | Formate l'argument sous forme de nombre à virgule flottante en base 10, en utilisant la notation exponentielle. Représentation en majuscule pour le type E< | |