Java 1.5 - Tiger 5.0 et supérieur

Chapitres traités   

Dans cette étude, nous allons voir quelques nouveautés qu'apporte la nouvelle version du langage Java, dénommée Tiger. La particularité de cette version, c'est qu'elle apporte des nouveautés au niveau du langage lui-même, et également, comme d'habitude, propose de nouvelles classes intéressantes. Dans ce chapitre, nous allons voir quelques unes de ces nouveautés qui vont nous simplifier la tâche de façon appréciable.

 

Choix du chapitre Classe Scanner

Nous avons pu constater combien il est facile d'afficher des informations sur l'unité de "sortie standard - System.out" (par défaut, la fenêtre de la console) en appelant System.out.println(). Bizarrement, avant le JDK 5.0 (ou 1.5), il n'existait aucune méthode commode pour lire des entrées depuis la fenêtre de la console. Heureusement, cette situation vient d'être rectifiée.

La lecture d'une entrée au clavier s'effectue en construisant un Scanner attaché sur l'unité "entrée standard - System.in" :

Scanner clavier = new Scanner(System.in);

Les diverses méthodes de la classe Scanner permettent ensuite de lire les entrées. Par exemple, la méthode nextLine() permet de lire une ligne de saisie complète :

System.out.print("Quel est ton nom ? ");
String nom = clavier.nextLine();

Ici, nous utilisons la méthode nextLine() car la saisie pourrait contenir des espaces. Pour lire un seul mot (délimité par des espaces), appelez :

System.out.print("Quel est ton prénom ? ");
String prénom = clavier.next();

Pour lire un entier, utilisez la méthode nextInt() :

System.out.print("Quel est ton âge ? ");
int âge = clavier.nextInt();

Penser à importer le paquetage java.util.* ; ou java.util.Scanner ;
.

méthodes Caractéristiques
Scanner(InputStream in) Construit un objet Scanner à partir du flux de saisie. Peut-être utilisé pour d'autres type de flux et peut donc remplacer avantageusement BufferedReader.
String nextLine( ) Lit la prochaine ligne saisie.
String next( ) Lit le prochain mot saisi (délimité par un espace).
int nextInt( ) Lit et transforme la prochaine ligne de caractères qui représente un entier.
double nextDouble( ) Lit et transforme la prochaine ligne de caractères qui représente un nombre à virgule flottante.
boolean hasNext( ) Teste s'il y a un autre mot dans la saisie.
boolean hasNextInt( ) Teste si la prochaine suite de catactères représente un entier.
boolean hasNextDouble( ) Teste si la prochaine suite de catactères représente un nombre à virgule flottante.
void useLocale(Locale localité) Permet de changer de localité. Lorsque nous utilisons la classe Scanner dans un système d'exploitation réglé en zone française, le paramètre localité est positionné par défaut à Locale.FRENCH. Du coup en France, les nombres réels s'expriment au moyen de la virgule. Si vous faites une saisie depuis le clavier, cela ne pose pas de problème, bien au contraire. Malgré tout, si vous désirez effectuer la saisie en considérant qu'il s'agit d'un double c'est-à-dire en respectant l'écriture américaine, vous devez changer de localité. Placez alors la constante Locale.US en argument de cette méthode.

clavier.Clavier
package clavier;

import java.util.*;
import static java.lang.System.*;

public class Clavier {
   public static void main(String[] args) {
      Scanner saisie = new Scanner(in);
      out.print("Entier : ");
      int entier = saisie.nextInt();
      saisie.useLocale(Locale.US);
      out.println("Réel : ");
      double réel = saisie.nextDouble();
      out.println("Entier = "+entier);
      out.println("Réel = "+réel);
  }
}

Attention pour la saisie des nombres réels. En france, nous devons taper par exemple "12,5" au lien de "12.5". Si vous désirez effectuer la saisie avec le point comme séparateur de la partie entière avec la partie décimale, vous devez changer de localité afin que cela soit considéré comme nombre réel écrit sous la forme US (USA). Utilisez pour cela la méthode useLocale() en spécifiant l'argument Locale.US (par défaut : Locale.FRENCH).

 

Choix du chapitre Importation statique

Depuis le jdk 5.0 l'importation import a été amélioré de manière à permettre l'importation de méthodes et de champs statiques, et non plus simplement des classes.

Par exemple, si vous ajoutez la directive :

import static java.lang.System.*;

en haut de votre fichier source, vous pouvez utiliser les méthodes et les champs statiques de la classe System, sans préfixe du nom de classe :

out.print("Quel est ton âge ? "); // c'est-à-dire System.out.print()
exit(0); // c'est-à-dire System.exit

Vous pouvez également importer une méthode ou un champ spécifique :

import static java.lang.System.out;
print("Quel est ton âge ? "); // c'est-à-dire System.out.print()

Dans la pratique, il semble douteux que de nombreux programmeurs souhaitent abréger System.out ou System.exit. Le résultat peut être moins clair. Mais il existe des utilisations pratiques des imports statiques.

Par exemple, si vous utilisez un import statique pour la classe Math, vous pouvez utiliser des fonctions mathématiques d'une manière plus naturelle. Par exemple :

sqrt(pow(x, 2) + pow(y, 2))

semble plus clair que :

Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))

 

Choix du chapitre Nouveauté sur la boucle for

Le JDK 5.0 a introduit une construction de boucle performante qui vous permet de parcourir chaque élément d'un tableau (ainsi que d'autres collections d'éléments) sans avoir à vous préoccuper des valeurs d'indice.

La boucle for améliorée :

for (variable : collection) instruction

définit la variable donnée sur chaque élément de la collection, puis exécute l'instruction (qui, bien sûr, peut être un bloc). L'expression collection doit être un tableau ou un objet d'une classe qui implémente l'interface Iterable, comme ArrayList. Par exemple :

int[] tableau = new int[10];
for (int élément : tableau) System.out.println(élément); // affiche chaque élément du tableau sur une ligne séparée.

Il est conseillé de lire cette boucle sous la forme "pour chaque élément dans tableau".

Les concepteurs du langage Java ont envisager d'utiliser des mots clés comme foreach et in. Mais cette boucle a été ajoutée avec un peu de retard au langage Java et , au final, personne n'a voulu casser un ancien code qui contenait déjà des méthodes et des variables avec les mêmes nom (comme System.in).

Bien entendu, vous pourriez obtenir le même effet avec la boucle for traditionnelle :

int[] tableau = new int[10];
for (int élément=0; élément<10; élément++) System.out.println(tableau[élément]);

Toutefois, la boucle "for each" est plus concise et moins sujette à erreur (vous n'avez pas à vous inquiéter des valeurs d'indice de début et de fin, qui sont souvent pénibles).

La variable loop de la boucle "for each" parcourt les éléments d'un tableau, et non les valeurs d'indice.
.

La boucle "for each" est une amélioration agréable de la boucle traditionnelle si vous devez traiter tous les éléments d'une collection. Il y a toutefois de nombreuses opportunités d'utiliser la boucle for traditionnelle. Vous ne voudrez pas, par exemple, parcourir la totalité de la collection ou pourriez avoir besoin de la valeur d'indice à l'intérieur de la boucle.

 

Choix du chapitre Exemple récapitulatif

Nous allons mettre en oeuvre un exemple très simple qui permet de montrer l'intérêt de ces trois nouveautés. Il s'agit de construire un tableau d'entier dont la taille est déterminé par l'opérateur, et nous lui demandons ensuite de compléter chacune des cases du tableau avec les valeurs de son choix. Une fois que tableau est rempli, nous proposons juste un affichage récapitulatif :

Voici le codage correspondant :

testclavier.Main.java
 1 package testclavier;
 2 
 3 import static java.lang.System.*;
 4 import java.util.Scanner;
 5 
 6 public class Main {
 7    public static void main(String[] args) {
 8       Scanner clavier = new Scanner(in);
 9       out.print("Nombre de cases de votre tableau : ");
10       int nombre = clavier.nextInt();
11       int[] tableau = new int[nombre];
12       for (int indice=0; indice<nombre; indice++) {
13          out.print("tableau["+indice+"] = ");
14          tableau[indice] = clavier.nextInt();
15       }
16       out.println("Récapitulatif de votre saisie :");    
17       for (int élément : tableau) out.println(élément);
18    }
19 }
20

 

Choix du chapitre Enveloppe d'objets et autoboxing

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é.

Autoboxing

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.

Unboxing

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() ;

Autoboxing et Unboxing

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é.

Enveloppes de nombres et chaînes de caractères

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));
   }
}

A titre d'exemple, voici la description de la classe enveloppe Integer

Attributs java.lang.Integer
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 java.lang.Integer
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.
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.
static int highestOneBit(int valeur) Méthode statique qui renvoie la valeur du bit de poids fort du nombre entier passé en argument.
static int lowestOneBit(int valeur) Méthode statique qui renvoie la valeur du bit de poids faible du nombre entier passé en argument.
static int parseInt(String valeur) 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.
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 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.
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.

 

Choix du chapitre Mise en forme de l'affichage - printf()

Sans printf()

double x = 1000.0 / 3.0 ;
System.out.println(x) ;

Le résultat de cette suite d'instructions :

3333.3333333333335

Avec printf()

double x = 1000.0 / 3.0 ;
System.out.printf("%8.2f", x) ;

affiche x avec un gabarit dont la largeur de champ est de 8 caractères avec une précision de 2 caractères.

 3333.33

En fait, l'affichage contient un espace préalable suivi des sept caractères que compose le nombre du à la précision.

méthode toString()

Vous pouvez utiliser la conversion s pour mettre en forme des objets arbitraires.

Lorsqu'un objet arbitraire implémente l'interface Formattable, la méthode formatTo() de l'objet est appelée. Dans le cas contraire, c'est la méthode toString() qui est appelée pour transformer l'objet en chaîne.

public class TestPrintF {
   public static void main(String[] args) {
      Personne moi = 
   new Personne("REMY","Emmanuel", 46);
      System.out.println(moi);
      System.out.printf("%s", moi);
   }
}

class Personne {
   private String nom, prénom;
   private int âge;
   
   public Personne(String nom, 
                         String prénom, int âge) {
      this.nom = nom;
      this.prénom = prénom;
      this.âge = âge;
   }
   public String toString() {
      return prénom +' '+nom;
   }
}

Voici le résultat :

init:
deps-jar:
Compiling 1 source file to L:\BTS IRIS\TP Java\TestPrintF\build\classes
compile:
run:

Emmanuel REMY
Emmanuel REMY

BUILD SUCCESSFUL (total time: 1 second)

Les drapeaux

Le drapeau virgule ajoute des séparateurs de groupe :

System.out.printf("%,.2f", 1000.0 / 3.0) ;

affiche :

 3,333.33

Vous pouvez également afficher plusieurs drapeaux, par exemple "%,.2f", pour utiliser des séparateurs de groupe et inclure des nombres négatifs entre parenthèses.

Méthode statique String.format()

Vous pouvez utiliser la méthode String.format() pour créer une chaîne mise en forme sans l'afficher :

String message = String.format("Salut, %s. Cette année vous aurez %d ", nom, âge) ;

Formatage de la date

System.out.printf("%tc", new Date()) ;

affiche la date et l'heure courante au format :

ven. févr. 17 17:36:28 CET 2006

Comme nous pouvons le constater dans le tableau ci-contre, certains formats produisent une partie seulement d'une date donnée, par exemple le jour ou le mois. Il serait pourtant assez stupide de fournir la date plusieurs fois pour la mettre totalement en forme. c'est pourquoi une chaîne peut indiquer l'indice de l'argument à mettre en forme. L'indice doit suivre immédiatement le % et se terminer par un $. Ainsi :

System.out.printf("%1$s %2$tB %2$te, %2$tY", "Date du jour : ", new Date()) ;

affiche :

Date du jour : février 20, 2006

Vous pouvez-aussi utiliser le drapeau <. Il indique qu'il faut utiliser l'argument avec le format qui précède. Ainsi l'instruction :

System.out.printf("%s %tB %<te, %<tY", "Date du jour : ", new Date()) ;

produit le même résultat que l'instruction précédente.

 

L'instruction System.out.print(x) permet d'afficher un nombre x à la console. Cette instruction affichera x avec le maximum de chiffres différents de zéro (pour le type donné). Cela pose un problème si vous désirez afficher, par exemple, des €uros et des centimes.

Avant le JDK 5.0, l'affichage des nombres posait quelques problèmes. Heureusement cette nouvelle version a rapatriée la vénérable méthode printf() de la bibliothèque C. Il est possible de fournir plusieurs paramètres à la méthode printf(). En voici un exemple ci-dessous :

System.out.printf("Salut, %s. Cette année vous aurez %d ", nom, âge) ;

Chaque spécificateur de format qui commence pa le caractère % est remplacé par l'argument correspondant. Le caractère de conversion qui termine un spécificateur de format indique le type la valeur à mettre en forme : f est un nombre à virgule flottante, s une chaîne et d'une valeur décimale.

Conversion pour printf()

Voici les caractères de conversion à spécifier afin d'obtenir le résultat désiré :

Caractères de conversion Type Exemple
d
Entier décimal

159
x Entier hexadécimal 9F
o Entier octal 237
f Virgule fixe, virgule flottante 15.9
e Virgule flottante exponentielle 1.59e+01
g Virgule flottante générale (le plus court entre e et f)  
a Virgule flottante hexadécimale 0x1.FCCDp3
s Chaîne de caractères Salut
c Caractère S
b Valeur booléenne true
h Code de hachage 42628B2
tx Date et heure (voir plus loin)
% Symbole de pourcentage %
n Séparateur de ligne de fonction de la plateforme  

Drapeaux

Vous pouvez également spécifier des drapeaux qui contrôleront l'apparence des résultats mis en forme.

Drapeau Rôle Exemple
+
Affiche le signe des nombres positifs et négatifs +3333.33
espace Ajoute un espace avant les nombres positifs. |  3333.33|
0 Ajoute des zéros préalables. 003333.33
- Justifie le champ à gauche |3333.33|
( Entoure le nombre négatif de parenthèses (3333.33)
, Ajoute des séparateurs de groupe. 3,333.33
# (pour format f) Inclut toujours une décimale. 3,333
# (pour format x ou o) Ajoute le préfixe 0x ou 0. 0xcafe
^ Transforme en majuscules. 0xCAFE

$

Indique l'indice de l'argument à mettre en forme ; par exemple, %1$d %1$x affiche le premier argument en décimal et hexadécimal. 159 9F
< Met en forme la même valeur que la spécification précédente ; par exemple, %d %<x affiche le même nombre en décimal et en hexadécimal. 159 9F

Formatage de la date


Dans cette rubrique, nous allons voir brievement les options de mise en forme de la date et de l'heure au moyen de la méthode printf(). Exceptionnellement, nous utilisons un format à deux lettres commençant par t et se terminant par l'une des lettres suivantes :

Caractère de conversion Type Exemple
c
Date et heure complètes ven. févr. 17 17:40:05 CET 2006
F Date au format ISO 8601 2006-02-17
D Date au format américain 02/17/06
T Heure sur 24 heures 17:43:57
r heure sur 12 heures 05:44:37 PM
R Heure sur 24 heures sans secondes 17:45
Y Année sur quatre chiffres (avec zéros préalables, le cas échéant) 2006
y Deux derniers chiffres de l'année (avec zéro préalable, le cas échéant) 06
C Deux premiers chiffres de l'année (avec zéro préalable, le cas échéant) 20
B

Nom complet du mois février
b ou h Nom du mois abrégé févr.
m Mois sur deux chiffres (avec zéro préalable le cas échéant) 02
d Jour sur deux chiffres (avec zéro préalable, le cas échéant) 17
e Jour sur deux chiffres. 9
A Jour de la semaine complet vendredi
a Jour de la semaine abrégé ven.
j Jour de l'année sur trois chiffres (avec zéros préalables, le cas échéant), entre 001 et 366. 048
H Heure sur deux chiffres (avec zéro préalable, le cas échéant) , entre 00 et 23 21
k Heure sur deux chiffres (sans zéro préalable, le cas échéant) entre 0 et 23 8
I Heure sur deux chiffres (avec zéro préalable, le cas échéant) entre 01 et 12 09
l Heure sur deux chiffres (sans zéro préalable) , entre 1 et 12 9
M Minutes sur deux chiffres (avec zéro préalable, le cas échéant) 06
S Secondes sur deux chiffres (avec zéro préalable, le cas échéant) 09
L Millième de seconde, sur trois chiffres (avec zéros préalables, le cas échéant) 921
N Nanosecondes sur neuf chiffres (avec zéros préalables, le cas échéant) 656000000
P Indicateur du matin ou de l'après midi en majuscules PM
p Indicateur du matin ou de l'après midi en minuscule pm
z Décalage numérique RFC 822 du GMT +0100
Z Fuseau horaire CET
s Secondes depuis le 1970-01-01 00:00:00 GMT 1140209926
E Millièmes de seconde depuis le 1970-01-01 00:00:00 GMT 1140209926047

Choix du chapitre Méthodes ayant un nombre variable de paramètres

Avant le JDK 5.0, chaque méthode Java disposait d'un nombre fixe de paramètres. Il est toutefois maintenant possible de fournir des méthodes qui peuvent être appelées avec un nombre variable de paramètres (quelquefois appelés méthodes "varargs").

Analyse à l'aide de la méthode printf()

Dans le chapitre précédent, nous avons déjà utilisé une telle méthode, la méthode printf(). Par exemple, les appels :

System.out.printf("Salut, %s. Cette année vous aurez %d ", nom, âge) ;

et :

System.out.printf("%,.2f", 1000.0 / 3.0) ;

appelent tous deux la même méthode, même si l'un a trois paramètres et l'autre deux. La méthode printf() est définie comme ceci :

public class PrintStream {
   public PrintStream printf(String fmt, Object... args) {
      return format(fmt, args);
   }
}

Ici, l'ellipse (...) fait partie du code Java. Elle montre que la méthode peut recevoir un nombre arbitraire d'objets (en plus du paramètre fmt).
.

La méthode printf() reçoit en fait deux paramètres, la chaîne format() est un tableau Object[] qui contient tous les autres paramètres (si l'appelant fournit des entiers ou autres valeurs de type primitif, l'autoboxing les transforme en objets). Elle dispose maintenant de la tâche non enviable d'analyser la chaîne fmt et de se conformer au spécificateur de format ith avec la valeur args[i].

Autrement dit, pour l'implémenteur de printf(), le type de paramètre Object... est exactement le même que Object[].
.

Le compilateur doit transformer chaque appel à printf(), en regroupant les paramètres dans un tableau et en procédant à l'autoboxing en fonction des besoins. Ainsi, en utilisant la méthode printf() comme ci-dessous :

System.out.printf("%d %s", n, "Bonjour" ) ;

Le compilateur transforme cet appel de la façon suivante :

System.out.printf("%d %s", new Object[] { new Integer(n), "Bonjour"}) ;

Définition de nos propres méthodes avec un nombre variable de paramètres

Vous pouvez définir vos propres méthodes avec des paramètres variables et spécifier tout type pour les paramètres, même un type primitif. Voici justement un exemple simple : une méthode max() qui calcule le maximum d'un nombre variable de valeurs réelles :

public class Calcul {
   public static void main(String[] args) {
      double m = max(3.1, 40.4, -5);
      System.out.println("Valeur maximale : "+m);
   }
   public static double max(double... valeurs) {
      double plusGrande = Double.MIN_VALUE;
      for (double v : valeurs) 
         if (v>plusGrande) 
            plusGrande = v;
      return plusGrande;
   }
}

Le compilateur transfère un nouveau double[] {3.1, 40.4, -5} à la méthode max().
.