next up previous contents index
suivant: 2.7 Un exemple : monter: 2. Variables et instructions précédent: 2.5 Un exemple :   Table des matières   Index


2.6 Tableaux

Un tableau est un objet rassemblant un nombre donné de variables déclarées d'un même type et installées consécutivement en mémoire ; ces variables sont appelées les éléments du tableau ; le nombre d'éléments, appelé la longueur du tableau, est représenté par le champ length du tableau ; ce champ est non modifiable ; un tableau de longueur nulle est dit vide.

À tout type correspond un type de tableaux obtenu en suffixant [] à son nom : par exemple, les types int[] des tableaux d'entiers, String[] des tableaux de chaînes de caractères, int[][] des tableaux de tableaux d'entiers. Les tableaux ne sont pas des valeurs, mais des objets qui n'existent dans la mémoire que s'ils sont créés. La déclaration d'une variable de type tableau ne crée pas de tableau :

   int[] a;

Un tableau est créé grâce à l'opérateur new[]. L'expression spécifiant la longueur, entre les crochets « [ » et « ] », doit être de type int (ou d'un sous-type de int), et n'est pas nécessairement constante ; sa valeur doit être positive ou nulle. Les éléments d'un tableau sont toujours initialisés à la valeur nulle de leur type (figure [*]).

Figure: Création d'un tableau de 4 int, affectation à une variable t.
\begin{figure}\ \begin{center}
\ \leavevmode
\ \fbox{
\ \epsfig{file=fig/tab1.eps}
\ }\ \ \ \end{center}\ \end{figure}

La valeur de cette expression est une référence au tableau créé : il s'agit d'une nouvelle sorte de valeur, différente des valeurs primitives. Comme toute valeur, celle-ci peut être affectée à une variable, qui doit avoir été déclarée de type int[] :

  int[] t = new int[4];

Cette définition déclare t comme un nom dont le type est « tableau de int» ; l'évaluation de new int[4] crée un objet qui comporte un bloc de mémoire pouvant contenir quatre int ; enfin, t est initialisé par une référence à cet objet, et chacun de ses quatre éléments est initialisé à 0 (figure [*]).

Il est aussi possible de définir un tableau en initialisant explicitement ses éléments, comme dans l'exemple suivant qui initialise a[0] à 1, a[1] à 2, etc. (figure [*]) :

   int[] a = new int[] {1, 2, 3, 4}; 
   int[] a = {1, 2, 3, 4};            // FORME SIMPLIFIÉE

La seconde forme ne peut être employée que lors de la définition d'une variable ; la première forme, new $t$[] { ... }, est une expression de type $t$[] qui définit et initialise un tableau anonyme et peut être employée dans d'autres contextes qu'une initialisation, par exemple en argument d'une fonction.

Figure: Création d'un tableau avec initialisation explicite des éléments.
\begin{figure}\ \begin{center}
\ \leavevmode
\ \fbox{
\ \epsfig{file=fig/tab1i.eps}
\ } \end{center} \end{figure}

Les éléments d'un tableau sont toujours accédés par indexation à partir de zéro : les quatre éléments du tableau a sont a[0], a[1], a[2] et a[3]. Ces a[$i$], et plus généralement a[exp], pour une expression arithmétique exp de type int (ou d'un sous-type de int), sont des variables désignant les éléments du tableau, et peuvent donc être le membre gauche d'une affectation :

  int k = ...;
  a[k+1] = 12;

C'est une erreur de tenter d'accéder à un élément hors des bornes du tableau (par exemple a[-4], a[4]). Cette tentative déclenche à l'exécution l'exception ArrayIndexOutOfBoundsException.

Un tableau, une fois défini, ne peut pas être redimensionné : on ne peut pas lui ajouter ou lui retirer des éléments, ni affecter une valeur à son champ length. C'est pourquoi le type java.util.List (voir §  [*]), qui n'a pas cette limitation, est fréquemment utilisé à la place d'un type tableau. Cependant, la longueur d'un tableau n'a pas à être connue à la compilation (ce qui est une contrainte des tableaux en Pascal, C et C++) ; on peut définir un tableau dont la longueur, puis les éléments, sont lus sur l'entrée standard en cours d'exécution, ou encore dont la longueur est calculée à l'exécution, par une fonction quelconque :

  double[] t = new double[f(n)];

Tous les tableaux sont à allocation dynamique.


2.6.0.0.1 Tableaux et fonctions

Un tableau peut être argument d'une fonction ou retourné par une fonction, ce qui rend la manipulation des tableaux plus simple en Java que dans d'autres langages. Par exemple, la fonction sommerÉléments retourne la somme des éléments d'un tableau, la fonction tableauAléatoire construit un tableau aléatoire de taille donnée et retourne une référence à ce tableau :

  static double sommerÉléments(double[] a) {
    double somme = 0;
    for (int i=0; i<a.length; i++) {
      somme += a[i];
    }
    return somme;
  }

  static double[] tableauAléatoire(int n) {
    double[] b = new double[n];
    for (int i=0; i<b.length(); i++) {
      b[i] = Math.random();
    }
    return b;
  }

  public static void main (String[] args) {
    double[] t = tableauAléatoire(10)
    double s = sommerÉléments(t);
    // ...
  }

Le tableau argument est passé par valeur ; or, la valeur de cet argument est une référence à un tableau ; c'est cette référence qui sert à initialiser le paramètre correspondant, lors de l'invocation de la fonction. Ceci permet à la fonction de modifier les éléments du tableau. Par exemple, on échange la valeur de deux éléments d'un tableau par :

  static void échangerÉléments(int[] a, int m, int n) {
    int v = a[m] ;
    a[m] = a[n] ;
    a[n] = v;
  }

  public static void main (String[] args) {
    int[] a = new int[] {1, 2, 3, 4, 5, 6};
    échangerÉléments(a, 2, 4);            // a = {1, 2, 5, 4, 3, 6}
    // ...
  }

Il est souvent commode d'utiliser un tableau pour rassembler plusieurs valeurs de retour d'une fonction, quand ces valeurs sont de même nature et que leur nombre n'est pas connu. Par exemple, si l'on demande de calculer les solutions réelles d'une équation, on pourra retourner ces solutions dans un tableau :

  static double[] solutions(...) { ... }

Une invocation de cette fonction aura la forme suivante :

  static double[] racines = solutions( ... );

Si la fonction solutions crée un tableau dont la longueur est le nombre de solutions, on peut alors accéder à ce nombre par racines.length et, selon cette valeur, aux racines éventuelles racines[0], racines[1], etc.


2.6.0.0.2 Tableaux pluridimensionnels

Tout ceci s'applique directement aux tableaux pluridimensionnels. Par exemple, un tableau bidimensionnel d'éléments de type $t$ est simplement un tableau dont les éléments sont des références à des tableaux d'éléments de type $t$ : le type de ces tableaux bidimensionnels est $t$[][]. La déclaration du nom du tableau ne crée aucun objet :

  int[][] t;

Figure: Tableau bidimensionnel : déclaration d'une variable et création.
\begin{figure}\ \begin{center}
\leavevmode
\fbox{
\epsfig{file=fig/tab2.eps}
} \end{center} \end{figure}

Deux niveaux de création sont nécessaires :

    t = new int[2][];

crée un tableau de longueur 2, dont les éléments sont des références à des tableaux de int, ces éléments étant initialisés à null. Ensuite, une boucle permet de créer chacune des lignes du tableau bidimensionnel, les éléments de chaque ligne étant initialisés à 0 (figure [*]) :

    for (int i=0; i<t.length; i++) t[i] = new int[3];

On accède à ses éléments par double indexation : t[0][0], t[0][1] et t[0][2] pour la première ligne, t[1][0], t[1][1] et t[1][2] pour la seconde. Comme t est un tableau, une indexation partielle est admise : les expressions t[0] et t[1] désignent des tableaux de longueur 3. Ces deux niveaux de création peuvent être effectués en une seule fois, par l'affectation suivante, qui crée un tableau rectangulaire à 2 lignes et 3 colonnes, dont tous les éléments sont nuls :

    t = new int[2][3];

Il est aussi possible de créer des tableaux non rectangulaires, chaque ligne ayant son nombre d'éléments :

    for (int i=0; i<t.length; i++) t[i] = new int[i+1];

Enfin, on peut créer un tableau bidimensionnel en initialisant explicitement ses éléments de la façon suivante :

    t = new int[][] {
          new int[] {1, 2, 3},
          new int[] {4, 5, 6}
        };

Lors de la définition d'un nom, le constructeur new int[][] peut être omis :

    int[][] t = {
      {1, 2, 3},
      {4, 5, 6}
    };

Il est également facile de construire un tableau avec des lignes de longueurs différentes :

    t =  new int[][] {
      new int[] {1},
      new int[] {2, 3},
      new int[] {4, 5, 6}
    };


next up previous contents index
suivant: 2.7 Un exemple : monter: 2. Variables et instructions précédent: 2.5 Un exemple :   Table des matières   Index
Rene' LALEMENT 2001-11-07