↑
CHAPITRE 1

Le modĂšle Java

Plateforme, donnĂ©es, Ă©criture d’un programme

Vous savez dĂ©jĂ  programmer. Dans ce chapitre, vous allez dĂ©couvrir ce qui est propre Ă  Java : comment un programme se compile et s’exĂ©cute, comment vous organisez votre code, comment vous manipulez des donnĂ©es, puis comment vous Ă©crivez un programme complet.

Points essentiels
  • JVM, bytecode, JDK / JRE, javac / java
  • Classe, main, package, import (y compris *)
  • Types primitifs, variables (nommage, mots-clĂ©s), conversions et cast
  • RĂ©fĂ©rences, null, autoboxing, String (== / equals), parseInt
  • enum, final, portĂ©e, valeurs par dĂ©faut
  • OpĂ©rateurs, print / println / printf, if / switch, boucles, tableaux
  • Scanner, arguments args, commentaires et Javadoc

1.1Plateforme

1.1.1 – JVM et bytecode

Quand vous compilez un fichier Java, vous n’obtenez pas un programme rĂ©servĂ© Ă  Windows, macOS ou Linux. Le compilateur produit du bytecode : un code intermĂ©diaire, identique pour toutes les machines. Ce bytecode est stockĂ© dans des fichiers .class.

RĂŽle de la machine virtuelle

Qui exĂ©cute ce bytecode, alors ? La JVM (Java Virtual Machine). C’est un programme installĂ© sur votre ordinateur. Elle lit le bytecode et l’exĂ©cute. En d’autres termes, elle sert d’intermĂ©diaire entre le fichier .class et le systĂšme d’exploitation :

  • elle charge les classes et lance la mĂ©thode main ;
  • elle traduit le bytecode en instructions que la machine peut vraiment exĂ©cuter ;
  • elle gĂšre la mĂ©moire (notamment le ramasse-miettes) ;
  • elle masque les diffĂ©rences entre les systĂšmes (fichiers, processus, etc.).

Sans JVM, un fichier .class ne s’exĂ©cute pas. La commande java dĂ©marre prĂ©cisĂ©ment cette machine virtuelle.

ExĂ©cution indĂ©pendante du systĂšme d’exploitation

Vous compilez une seule fois. Le fichier .class obtenu n’est ni un .exe Windows ni un binaire Linux : c’est du bytecode portable. Vous pouvez donc copier la mĂȘme archive sur un autre systĂšme. L’exĂ©cution ne dĂ©pend pas de l’OS, Ă  condition qu’une JVM y soit installĂ©e.

C’est la portabilitĂ© de Java : votre programme ne « parle » pas Ă  Windows ou Ă  Linux, il parle Ă  la JVM. Chaque systĂšme a sa propre JVM ; le bytecode, lui, ne change pas.

Fichier .java  →  javac  →  Fichier .class (bytecode)  →  JVM  →  exĂ©cution
Du fichier source .java au bytecode .class, puis exécution par la JVM sur Windows, macOS et Linux
Le bytecode est le mĂȘme partout ; chaque systĂšme fournit sa JVM pour l’exĂ©cuter.
À retenir : vous distribuez le bytecode, pas un exĂ©cutable natif. La JVM dĂ©pend du systĂšme d’exploitation ; le fichier .class, non.

1.1.2 – JDK, JRE, javac et java

Quatre noms reviennent souvent. Ne les mélangez pas. Pour écrire et compiler du code, vous avez besoin du JDK. Pour seulement lancer un programme déjà compilé, le JRE suffit.

Outil RĂŽle
JDK Kit de développement : compilateur + JVM + bibliothÚques
JRE Exécution uniquement (JVM + bibliothÚques), sans javac
javac Compile un fichier .java en fichier .class
java Lance la JVM sur une classe qui contient main
javac App.java
java App
Pour développer : installez un JDK, pas seulement un JRE.

1.1.3 – Classe, mĂ©thode main, fichier source

En Java, tout votre code se trouve dans une classe. Pour lancer un programme, la JVM cherche une mĂ©thode bien prĂ©cise : main. C’est le point d’entrĂ©e.

Une classe public doit ĂȘtre dans un fichier du mĂȘme nom. Par exemple, la classe App se place dans le fichier App.java. Par convention, le nom d’une classe commence par une majuscule (PascalCase) : App, Livre, UserService. Voyons un programme minimal.

public class App {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}
Anatomie d’un programme Java : classe, main, arguments et affichage annotĂ©s
Les parties d’un programme minimal : classe, point d’entrĂ©e main, affichage (cliquer pour agrandir).
Signature de main : public static void main(String[] args). C’est cette mĂ©thode que la JVM appelle au dĂ©marrage. Le tableau args contient les arguments passĂ©s en ligne de commande (voir 1.3.7).

1.1.4 – package et import

DĂšs que le projet grandit, une seule classe ne suffit plus. Java range les classes dans des package — tout simplement des dossiers. La premiĂšre ligne du fichier dĂ©clare le package. Le nom du package doit correspondre au chemin des dossiers : le package app.model se place dans le dossier app/model/. Par convention, un nom de package s’écrit en minuscules : app, app.model — pas App.Model.

Pour utiliser une classe qui se trouve dans un autre package, vous avez deux possibilitĂ©s. Vous pouvez Ă©crire le nom complet Ă  chaque fois. Ou bien vous ajoutez un import, puis vous utilisez le nom court. En pratique, l’import est plus lisible.

Package Java = dossiers ; import pour utiliser une classe d’un autre package
java.util.Scanner in = new java.util.Scanner(System.in); // sans import

Import d’une classe

package app;

import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println(in.nextLine());
        in.close();
    }
}

Quand vous compilez et lancez le programme, vous devez tenir compte du package :

javac app/App.java
java app.App

Import avec *

Vous n’avez pas envie d’écrire chaque classe une par une ? L’écriture import java.util.* importe toutes les classes du package java.util, par exemple Scanner, Random ou Date.

import java.util.*;

public class App {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Random r = new Random();
        System.out.println(in.nextLine() + " " + r.nextInt(10));
        in.close();
    }
}
Le * ne descend pas dans les sous-packages. Ainsi, import java.util.* n’importe pas java.util.concurrent.ConcurrentHashMap. Il faudrait Ă©crire import java.util.concurrent.*, ou importer directement la classe.
Le package java.lang (String, System, Integer
) est importĂ© automatiquement. Vous n’avez donc pas besoin d’écrire import java.lang.*.
En projet, on prĂ©fĂšre souvent un import explicite pour chaque classe : c’est plus lisible. L’étoile reste pratique en cours, ou quand un fichier utilise beaucoup de classes du mĂȘme package.

1.2Données

Un programme manipule des valeurs. En Java, vous distinguez deux grandes familles : les valeurs simples (un entier, un boolĂ©en
) et les objets. Commençons par les valeurs simples.

1.2.1 – Types primitifs

Java propose huit types primitifs. En pratique, vous utiliserez surtout int, double, boolean et char.

Type Usage Valeur par défaut Exemple
int Entier par défaut 0 int n = 10;
long Grand entier (suffixe L) 0L long x = 8_000_000_000L;
double Nombre décimal par défaut 0.0 double p = 3.14;
float Décimal 32 bits (suffixe f) 0.0f float f = 1.5f;
boolean Vrai ou faux false boolean ok = true;
char Un caractĂšre Unicode '\u0000' char c = 'A';
byte, short Entiers plus petits — rarement nĂ©cessaires 0 byte b = 120;

Avez-vous remarquĂ© la colonne « valeur par dĂ©faut » ? Elle concerne les attributs d’une classe (voir 1.2.9). Une variable locale n’a pas de valeur par dĂ©faut : vous devez l’initialiser vous-mĂȘme.

1.2.2 – Variables

Une variable associe un nom Ă  une valeur d’un certain type. Pour la dĂ©clarer, vous Ă©crivez le type, puis le nom, puis Ă©ventuellement une valeur initiale. Choisissez un nom clair : il doit dĂ©crire ce que contient la variable.

int annee = 2026;
double prix = 12.5;
boolean dispo = true;
String titre = "Dune";

Nommage

Un nom de variable peut contenir des lettres, des chiffres, _ et $. Il ne doit pas commencer par un chiffre. Java distingue les majuscules et les minuscules : annee et Annee sont deux variables différentes. Par convention, vous écrivez les variables et les méthodes en camelCase : nbLivres, titreDuLivre, afficherTitre.

int nbLivres = 3;     // OK
int 2titres = 3;      // ❌ interdit : commence par un chiffre
int titre-livre = 1;  // ❌ interdit : tiret

Mots-clés à éviter

Un nom de variable ne peut pas ĂȘtre un mot rĂ©servĂ© du langage. Des mots comme class, new ou int sont dĂ©jĂ  pris par Java.

Famille Exemples (interdits comme nom)
Types int, double, boolean, void, class, enum
ContrĂŽle if, else, for, while, switch, return, break
Autres public, static, new, package, import, final, this, null, true, false
int class = 1;    // ❌ interdit
int new = 2;      // ❌ interdit
int classe = 1;   // OK : ce n’est pas le mot-clĂ© class

1.2.3 – Conversions et cast

Un int tient facilement dans un double : Java fait la conversion tout seul. On parle d’élargissement. L’inverse est plus dĂ©licat : vous pouvez perdre de l’information. Dans ce cas, vous devez Ă©crire un cast explicite.

int n = 10;
double d = n;          // OK : 10.0

double x = 3.9;
int k = (int) x;       // 3 : la partie décimale est perdue

int grand = 300;
byte b = (byte) grand; // débordement possible : résultat trompeur
Sens Écriture Risque
int → double automatique Aucun
double → int (int) Troncature, pas d’arrondi
type Ă©troit ← type large cast obligatoire DĂ©bordement silencieux
Le cast ne « corrige » pas une valeur : (int) 3.9 donne 3, pas 4. La partie décimale est simplement coupée.

1.2.4 – RĂ©fĂ©rences et null

Tout ce qui n’est pas un type primitif est un objet. Imaginez une fiche de bibliothĂšque : la fiche n’est pas le livre, elle indique oĂč le trouver. Une variable objet fonctionne de la mĂȘme façon : elle contient une rĂ©fĂ©rence (une adresse en mĂ©moire), pas l’objet lui-mĂȘme.

String a = "Java";   // a référence un objet String
String b = a;        // b rĂ©fĂ©rence le mĂȘme objet
a = null;            // a ne rĂ©fĂ©rence plus rien ; l’objet peut rester atteint via b
RĂ©fĂ©rences Java : deux variables peuvent pointer vers le mĂȘme objet ; null signifie aucune rĂ©fĂ©rence

Comme vous pouvez le voir sur le schĂ©ma, plusieurs variables peuvent pointer vers le mĂȘme objet. null signifie « aucune rĂ©fĂ©rence ». Si vous utilisez une variable qui vaut null, Java lĂšve une NullPointerException.

Primitif vs référence : un int a toujours une valeur. Une variable objet, elle, peut valoir null.

1.2.5 – Autoboxing (int / Integer)

Chaque type primitif a une version objet : int devient Integer, double devient Double, et ainsi de suite. Java convertit automatiquement dans les deux sens. On parle d’autoboxing (primitif → objet) et d’unboxing (objet → primitif).

Pourquoi est-ce utile ? Parce que les collections n’acceptent que des objets. Vous Ă©crivez donc List<Integer>, et non List<int>.

Integer n = 3;     // autoboxing : int → Integer
int x = n;         // unboxing  : Integer → int
PiĂšge : si un Integer vaut null et que vous le convertissez en int, Java lĂšve une NullPointerException.

1.2.6 – String : immuabilitĂ©, == et equals

String est une classe. Une variable de type String est donc une référence. De plus, les chaßnes sont immuables : vous ne modifiez pas une chaßne existante, vous en créez une nouvelle.

Sur un primitif, == compare la valeur. Sur un objet, == compare les rĂ©fĂ©rences : est-ce le mĂȘme objet en mĂ©moire ? Pour comparer le contenu de deux chaĂźnes, vous utilisez equals.

int a = 5, b = 5;
System.out.println(a == b);       // true : mĂȘme valeur

String u = "Java";
String v = "Java";
String w = new String("Java");

System.out.println(u == v);       // souvent true (pool de littĂ©raux) — ne pas s’y fier
System.out.println(u == w);       // false : deux objets
System.out.println(u.equals(w));  // true  : mĂȘme contenu

String s = null;
System.out.println("Java".equals(s)); // false, sans exception
// s.equals("Java");                  // ❌ NullPointerException
RĂšgle : pour les primitifs, utilisez ==. Pour les objets (String, etc.), utilisez equals. Si la variable peut ĂȘtre null, prĂ©fĂ©rez "texte".equals(variable) : cela Ă©vite une exception.

1.2.7 – String vers un nombre

Quand l’utilisateur tape au clavier, ou quand vous passez un argument en ligne de commande, vous rĂ©cupĂ©rez souvent un String — du texte, pas un nombre.

Or vous ne pouvez pas calculer directement avec du texte. Il faut d’abord le convertir. Java fournit pour cela des mĂ©thodes toutes faites :

int n = Integer.parseInt("42");
double p = Double.parseDouble("3.14");
long g = Long.parseLong("8000000000");

Comme vous pouvez le voir, parseInt donne un int, parseDouble un double, et parseLong un long.

Attention : le texte doit vraiment représenter un nombre. Si vous écrivez Integer.parseInt("abc"), Java lÚve une NumberFormatException (vous verrez les exceptions en détail au chapitre 5).

1.2.8 – enum : un type à valeurs fixes

Parfois, une valeur ne peut prendre que quelques possibilitĂ©s bien dĂ©finies : par exemple roman, BD ou essai. Un enum vous permet de nommer ces constantes. Ce n’est pas un simple entier : c’est un type Ă  part entiĂšre.

Par convention, le nom de l’enum s’écrit en PascalCase (Genre, comme une classe), et chaque constante en MAJUSCULES : ROMAN, BD, ESSAI.

enum Genre {
    ROMAN, BD, ESSAI
}

Genre g = Genre.ROMAN;

switch (g) {
    case ROMAN -> System.out.println("Récit");
    case BD    -> System.out.println("Bande dessinée");
    case ESSAI -> System.out.println("Essai");
}

for (Genre x : Genre.values()) {
    System.out.println(x);
}
Pour l’instant, retenez les constantes et la mĂ©thode values(). Les constructeurs et les mĂ©thodes sur un enum seront vus au chapitre 2.

1.2.9 – final, portĂ©e, valeurs par dĂ©faut

Le mot-clé final

Le mot-clĂ© final s’applique Ă  une variable pour dire : « cette variable ne pourra recevoir qu’une seule valeur ». Une fois cette valeur fixĂ©e, vous ne pouvez plus la changer.

La façon la plus simple consiste à donner la valeur dÚs la déclaration. Pour une constante nommée « une fois pour toutes », on écrit souvent le nom en MAJUSCULES_AVEC_UNDERSCORES : MAX_LIVRES, TAUX_TVA.

final int MAX_LIVRES = 10;
// MAX_LIVRES = 11; // ❌ interdit : la valeur est dĂ©jĂ  fixĂ©e

Vous pouvez aussi dĂ©clarer une variable final sans l’initialiser tout de suite. Java accepte alors une premiĂšre affectation plus loin dans le code. AprĂšs cette premiĂšre Ă©criture, toute nouvelle affectation est refusĂ©e.

final int annee;          // pas encore de valeur

if (choix == 1) {
    annee = 2026;         // premiÚre (et seule) affectation autorisée
} else {
    annee = 2025;         // premiùre affectation dans l’autre branche
}

// annee = 2030;          // ❌ interdit : annee a dĂ©jĂ  reçu sa valeur
System.out.println(annee);
Attention : le compilateur vĂ©rifie que la variable final reçoit bien une valeur avant d’ĂȘtre lue, et qu’elle n’est Ă©crite qu’une seule fois sur chaque chemin possible du programme.
En rĂ©sumĂ© pour final : vous fixez la valeur une fois — soit Ă  la dĂ©claration, soit plus tard avec une premiĂšre affectation — puis la variable devient constante.

PortĂ©e d’une variable locale

La portĂ©e d’une variable locale s’arrĂȘte Ă  la fin du bloc { } oĂč vous l’avez dĂ©clarĂ©e. En dehors de ce bloc, la variable n’existe plus.

if (true) {
    int x = 1;     // x n’existe que dans ce if
}
// System.out.println(x); // ❌ erreur : x hors de portĂ©e

Valeurs par défaut

DerniĂšre distinction, essentielle. Un attribut de classe reçoit automatiquement une valeur par dĂ©faut. Une variable locale n’en a pas : le compilateur refuse de la lire tant que vous ne l’avez pas initialisĂ©e.

public class Demo {
    int n;          // 0
    boolean ok;     // false
    double d;       // 0.0
    String s;       // null

    void m() {
        int x;      // pas de valeur par défaut
        // System.out.println(x); // ❌ le compilateur refuse
        x = 1;
        System.out.println(x);
    }
}
Les attributs seront repris au chapitre 2. Pour l’instant, retenez ceci : une variable locale doit ĂȘtre initialisĂ©e ; un attribut reçoit une valeur par dĂ©faut (0, false ou null).

1.3Écriture d’un programme

Maintenant que vous connaissez les types et les variables, il reste Ă  calculer, Ă  prendre des dĂ©cisions, Ă  rĂ©pĂ©ter des actions et Ă  lire ce que l’utilisateur tape. C’est ce que vous ferez dans presque tous vos programmes.

1.3.1 – OpĂ©rateurs

Les opĂ©rateurs s’appliquent aux variables vues en 1.2.2. Deux piĂšges reviennent souvent : la division entre entiers, et la diffĂ©rence entre n++ et ++n.

Famille Opérateurs
Arithmétique + - * / %
Comparaison == != < > <= >=
Logique && || !
Affectation composée += -= *= /= %=
Incrément / décrément ++ --
int n = 5;
n += 2;          // 7
n++;             // 8  (post-incrément : utilise n puis ajoute 1)
++n;             // 9  (pré-incrément  : ajoute 1 puis utilise n)

int a = 3;
int b = a++;     // b = 3, puis a = 4
int c = ++a;     // a = 5, puis c = 5

Type du résultat

Quand vous mélangez des types dans une opération, Java ne « invente » pas un type au hasard. Le type du résultat correspond toujours au type le plus large parmi les opérandes.

Du plus étroit au plus large, retenez cette échelle :

byte  <  short  <  int  <  long  <  float  <  double  <  String

En pratique :

  • byte et int → rĂ©sultat en int
  • int et long → rĂ©sultat en long
  • long et double → rĂ©sultat en double
  • un nombre et un String avec + → rĂ©sultat en String (concatĂ©nation)
byte b = 2;
int n = 10;
// byte r = b + n;   // ❌ le rĂ©sultat est un int, pas un byte
int r = b + n;       // OK : 12

int i = 5;
long L = 2L;
long s = i + L;      // OK : le résultat est un long

System.out.println(3 + " livres"); // "3 livres" : String
À retenir : avec byte et short, Java passe souvent par int avant de calculer. C’est pourquoi byte + byte donne aussi un int.

L’opĂ©rateur ternaire remplace un if / else qui choisit une valeur. Pratique, non ?

String statut = (annee >= 2000) ? "récent" : "ancien";
Division entiÚre : 5 / 2 donne 2, car les deux opérandes sont des entiers. Pour obtenir un résultat décimal, écrivez par exemple 5 / 2.0.

Exercice de réflexion

Avant de continuer, testez-vous. Sans exĂ©cuter le programme, essayez de trouver les valeurs finales. Souvenez-vous : * a prioritĂ© sur + et -, et ++a / --d se font avant d’utiliser la valeur, alors que c-- utilise d’abord la valeur, puis dĂ©crĂ©mente.

Que valent x, a, b, c et d aprĂšs ces instructions ?

int a = 1, b = 2, c = 3, d = 4;
int x = ++a - ++b * c-- + --d;

1.3.2 – Affichage : print, println et printf

Pour afficher du texte Ă  l’écran, Java vous propose trois mĂ©thodes courantes sur System.out.

System.out.println affiche un texte, puis passe Ă  la ligne suivante. System.out.print affiche sans passer Ă  la ligne. C’est utile pour une invite de saisie : le curseur reste juste Ă  cĂŽtĂ© du message.

System.out.print("Titre : ");     // curseur reste sur la mĂȘme ligne
System.out.println("Dune");       // affiche puis nouvelle ligne
System.out.println(2026);         // accepte aussi les primitifs
System.out.println("Dune" + " (" + 1965 + ")"); // message composé

Et si vous voulez formater proprement un message avec des variables ? Utilisez System.out.printf. Vous écrivez un modÚle (une chaßne avec des emplacements), puis vous passez les valeurs à insérer.

String titre = "Dune";
int annee = 1965;
double prix = 12.5;

System.out.printf("Titre : %s%n", titre);
System.out.printf("Année : %d%n", annee);
System.out.printf("Prix : %.2f €%n", prix);
System.out.printf("%s (%d) coĂ»te %.2f €%n", titre, annee, prix);
System.out.println(titre + " (" + annee + ") coĂ»te " + prix + " €");
Emplacement RĂŽle Exemple
%s Texte (String) %s → Dune
%d Entier %d → 1965
%f Nombre dĂ©cimal %.2f → deux chiffres aprĂšs la virgule
%n Retour à la ligne équivalent portable de \n
En rĂ©sumĂ© : print et println affichent tel quel ; printf assemble un texte formatĂ© Ă  partir d’un modĂšle et de valeurs.

1.3.3 – if et switch

Quand vous devez tester une condition, vous utilisez un if. Quand vous devez choisir parmi quelques cas précis (int, String ou enum), un switch est souvent plus lisible.

if (annee >= 2000) {
    System.out.println("XXIe siĂšcle");
} else if (annee >= 1900) {
    System.out.println("XXe siĂšcle");
} else {
    System.out.println("Avant 1900");
}

Avec un switch « classique », chaque case se termine en gĂ©nĂ©ral par break. Sans break, l’exĂ©cution continuerait dans le cas suivant (c’est le fall-through).

int choix = 2;
switch (choix) {
    case 1:
        System.out.println("Ajouter");
        break;
    case 2:
        System.out.println("Lister");
        break;
    case 3:
        System.out.println("Quitter");
        break;
    default:
        System.out.println("Inconnu");
        break;
}

Depuis Java rĂ©cent, vous pouvez aussi Ă©crire une forme plus courte avec des flĂšches ->. Dans ce cas, vous n’avez pas besoin de break :

switch (choix) {
    case 1 -> System.out.println("Ajouter");
    case 2 -> System.out.println("Lister");
    case 3 -> System.out.println("Quitter");
    default -> System.out.println("Inconnu");
}
À retenir : dans le switch classique, n’oubliez pas break aprùs chaque cas, sauf si vous voulez volontairement enchaüner plusieurs cas.

1.3.4 – for, while, do-while, break, continue

Si vous connaissez Ă  l’avance le nombre de tours, utilisez un for. Si le nombre de tours dĂ©pend d’une condition, utilisez un while : le test se fait avant chaque tour. Si vous devez exĂ©cuter le corps de la boucle au moins une fois, utilisez un do-while : le test se fait aprĂšs le premier tour.

for (int i = 0; i < 3; i++) {
    System.out.println(i);
}

int n = 3;
while (n > 0) {                    // 0, 1 ou plusieurs tours
    System.out.println(n);
    n--;
}

int x = 0;
do {                               // au moins un tour
    System.out.println(x);
    x++;
} while (x < 3);

for (int i = 0; i < 10; i++) {
    if (i == 2) continue;          // saute la suite de ce tour
    if (i == 5) break;             // sort de la boucle
    System.out.println(i);         // 0 1 3 4
}
continue saute la fin du tour en cours et passe au suivant. break sort complùtement de la boucle. Vous verrez aussi le parcours d’un tableau avec for (
 : 
) juste aprùs, en 1.3.5.

Exercice de réflexion

Maintenant que vous avez vu continue et break, testez votre lecture d’un programme un peu plus riche. Sans l’exĂ©cuter, essayez de prĂ©voir exactement ce qui s’affiche Ă  l’écran. Vous devez suivre Ă  la fois la boucle, le test pair/impair et l’accumulation de total.

Que s’affiche Ă  la console aprĂšs l’exĂ©cution de ce programme ?

int total = 0;
for (int i = 1; i <= 8; i++) {
    if (i % 2 == 0) {
        continue;
    }
    total = total + i;
    System.out.println("i=" + i + " total=" + total);
    if (total >= 9) {
        break;
    }
}
System.out.println("fin total=" + total);

1.3.5 – Tableaux (1D et 2D)

Un tableau a une taille fixe, choisie au moment de sa crĂ©ation. Les index commencent Ă  0. La propriĂ©tĂ© length vous donne le nombre d’élĂ©ments.

Pour dĂ©clarer un tableau, vous avez deux Ă©critures possibles. La plus courante place les crochets [] juste aprĂšs le type, donc avant le nom de la variable : int[] tab. Java accepte aussi l’écriture int tab[], avec les crochets aprĂšs le nom. Les deux formes crĂ©ent le mĂȘme type de variable.

int[] notes = new int[3];   // forme recommandée : [] avant le nom
int notes2[] = new int[3];  // forme aussi acceptée : [] aprÚs le nom

notes[0] = 12;
notes[1] = 15;
notes[2] = 9;

String[] titres = {"Dune", "1984", "Névrose"};

for (int i = 0; i < titres.length; i++) {
    System.out.println(i + " : " + titres[i]);
}

// Parcours sans index (foreach) : chaque élément du tableau, un par un
for (String t : titres) {
    System.out.println(t);
}

int[][] grille = {
    {1, 2, 3},
    {4, 5, 6}
};
for (int i = 0; i < grille.length; i++) {
    for (int j = 0; j < grille[i].length; j++) {
        System.out.print(grille[i][j] + " ");
    }
    System.out.println();
}

// MĂȘme parcours avec foreach
for (int[] ligne : grille) {
    for (int valeur : ligne) {
        System.out.print(valeur + " ");
    }
    System.out.println();
}
En pratique, prĂ©fĂ©rez int[] tab : le type se lit d’un seul bloc (« un tableau d’entiers nommĂ© tab »). Si vous ne connaissez pas la taille Ă  l’avance, vous utiliserez les collections (chapitre 4). Pour un tableau Ă  deux dimensions, grille.length donne le nombre de lignes, et grille[i].length donne la taille de la ligne i.

1.3.6 – Saisie console (Scanner)

Pour lire ce que l’utilisateur tape au clavier, Java fournit la classe Scanner, branchĂ©e sur System.in. Vous utilisez nextLine() pour lire du texte, nextInt() pour un entier, et nextDouble() pour un nombre dĂ©cimal.

import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        System.out.print("Titre : ");
        String titre = in.nextLine();

        System.out.print("Année : ");
        int annee = in.nextInt();
        in.nextLine(); // consomme le retour Ă  la ligne restant

        System.out.println(titre + " (" + annee + ")");
        in.close();
    }
}
AprĂšs nextInt(), le retour Ă  la ligne (\n) reste dans le tampon. Si vous appelez ensuite nextLine() sans le consommer, vous lisez une ligne vide.

Exemple filé

Mettons tout cela bout à bout : un petit catalogue de titres, lus au clavier puis affichés.

import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] titres = new String[3];

        for (int i = 0; i < titres.length; i++) {
            System.out.print("Titre " + (i + 1) + " : ");
            titres[i] = in.nextLine();
        }

        System.out.println("--- Catalogue ---");
        for (String t : titres) {
            System.out.println("- " + t);
        }
        in.close();
    }
}

Exercice de réflexion

Exercice — CrĂ©ation et remplissage d’un tableau

Écrire un programme qui demande à l’utilisateur de saisir la taille d’un tableau.

La taille saisie doit ĂȘtre un entier strictement positif (n > 0). Tant que l’utilisateur saisit une valeur invalide, le programme doit lui redemander la taille.

Une fois une taille valide obtenue, crĂ©er le tableau, puis demander Ă  l’utilisateur de saisir les valeurs qui permettront de le remplir.

Contraintes :

  • utiliser une boucle do...while pour contrĂŽler la saisie de la taille ;
  • crĂ©er le tableau uniquement aprĂšs avoir obtenu une taille valide ;
  • parcourir ensuite le tableau pour demander et stocker ses valeurs.

1.3.7 – Arguments de la ligne de commande

Vous vous souvenez de String[] args dans la mĂ©thode main ? C’est un tableau de String : le mĂȘme type que String[] titres vu en 1.3.5.

La JVM remplit args avec ce que vous écrivez aprÚs le nom de la classe au lancement. Chaque mot séparé par un espace devient un élément du tableau.

Par exemple, si vous lancez :

java App Dune 1965

alors :

  • args.length vaut 2 ;
  • args[0] vaut "Dune" ;
  • args[1] vaut "1965" (toujours du texte, mĂȘme si ça ressemble Ă  un nombre).
public class App {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Aucun argument");
            return;
        }
        for (String a : args) {
            System.out.println(a);
        }
        int n = Integer.parseInt(args[0]);
        System.out.println(n * 2);
    }
}
java App Dune 1965
java App 21
Attention : tout ce qui arrive dans args est un String. Pour calculer avec un nombre passĂ© en argument, convertissez-le d’abord avec Integer.parseInt (voir 1.2.7).

1.3.8 – Commentaires et Javadoc

Java propose trois formes de commentaires. Les deux premiĂšres servent Ă  expliquer le code pour vous-mĂȘme. La troisiĂšme, appelĂ©e Javadoc, documente une mĂ©thode pour les personnes qui liront le code plus tard — y compris vous dans six mois.

// commentaire de ligne

/*
 * commentaire
 * sur plusieurs lignes
 */

/**
 * Affiche le titre d’un livre.
 * @param titre le titre Ă  afficher
 */
public static void afficher(String titre) {
    System.out.println(titre);
}

En résumé