Précédent Remonter Suivant

Chapitre 1  Les premiers pas en Java

Dans ce chapitre on donne quelques éléments simples de la programmation avec le langage Java : types, variables, affectations, fonctions. Ce sont des traits communs à tous les langages de programmation.

1.1  Le premier programme

1.1.1  Écriture et exécution

Commençons par un exemple simple de programme. C'est un classique, il s'agit simplement d'afficher Bonjour ! à l'écran.


// Voici mon premier programme
class Premier{
    public static void main(String[] args){
        System.out.println("Bonjour !");
        return;
    }
}

Pour exécuter ce programme il faut commencer par le copier dans un fichier. Pour cela on utilise un éditeur de texte (par exemple nedit) pour créer un fichier de nom Premier.java (le même nom que celui qui suit class). Ce fichier doit contenir le texte du programme. Après avoir tapé le texte, on doit le traduire (les informaticiens disent compiler) dans un langage que comprend l'ordinateur. Cette compilation se fait à l'aide de la commande1
unix% javac Premier.java
Ceci a pour effet de faire construire par le compilateur un fichier Premier.class, qui sera compréhensible par l'ordinateur, si on l'exécute à l'aide de la commande :
unix% java Premier
On voit s'afficher :
Bonjour !

1.1.2  Analyse de ce programme

Un langage de programmation est comme un langage humain. Il y a un ensemble de lettres avec lesquelles on forme des mots. Les mots forment des phrases, les phrases des paragraphes, ceux-ci forment des chapitres qui rassemblés donnent naissance à un livre. L'alphabet de Java est peu ou prou l'alphabet que nous connaissons, avec des lettres, des chiffres, quelques signes de ponctuation. Les mots seront les mots-clefs du langage (comme class, public, etc.), ou formeront les noms des variables que nous utiliserons plus loin. Les phrases seront pour nous des instructions, les paragraphes des fonctions (appelées méthodes dans la terminologie des langages à objets). Les chapitres seront les classes, les livres des programmes que nous pourrons faire tourner et utiliser.

Le premier chapitre d'un livre est l'amorce du livre et ne peut généralement être sauté. En Java, un programme débute toujours à partir d'une fonction spéciale, appelée main et dont la syntaxe immuable est :
    public static void main(String[] args)
Nous verrons plus loin ce que veulent dire les mots magiques public, static et void, args contient quant à lui des arguments qu'on peut passer au programme. Reprenons la fonction main :
    public static void main(String[] args){
        System.out.println("Bonjour !");
        return;
    }

Les accolades { et } servent à constituer un bloc d'instructions; elles doivent englober les instructions d'une fonction, de même qu'une paire d'accolades doit englober l'ensemble des fonctions d'une classe.

Noter qu'en Java les instructions se terminent toutes par un ; (point-virgule). Ainsi, dans la suite le symbole I signifiera soit une instruction (qui se termine donc par ;) soit une suite d'instructions (chacune finissant par ;) placées entre accolades.

La fonction effectuant le travail est la fonction System.out.println qui appartient à une classe prédéfinie, la classe System. En Java, les classes peuvent s'appeler les unes les autres, ce qui permet une approche modulaire de la programmation : on n'a pas à récrire tout le temps la même chose.

Notons que nous avons écrit les instructions de chaque ligne en respectant un décalage bien précis (on parle d'indentation). La fonction System.out.println étant exécutée à l'intérieur de la fonction main, elle est décalée de plusieurs blancs (ici 4) sur la droite. L'indentation permet de bien structurer ses programmes, elle est systématiquement utilisée partout.

La dernière instruction présente dans la fonction main est l'instruction return; que nous comprendrons pour le moment comme voulant dire : retournons la main à l'utilisateur qui nous a lancé. Nous en préciserons le sens à la section 1.6.

La dernière chose à dire sur ce petit programme est qu'il contient un commentaire, repéré par // et se terminant à la fin de la ligne. Les commentaires ne sont utiles qu'à des lecteurs (humains) du texte du programme, ils n'auront aucun effet sur la compilation ou l'exécution. Ils sont très utiles pour comprendre le programme.

1.2  Faire des calculs simples

On peut se servir de Java pour réaliser les opérations d'une calculette élémentaire: on affecte la valeur d'une expression à une variable et on demande ensuite l'affichage de la valeur de la variable en question. Bien entendu, un langage de programmation n'est pas fait uniquement pour cela, toutefois cela nous donne quelques exemples de programmes simples; nous passerons plus tard à des programmes plus complexes.
// Voici mon deuxième programme
public class PremierCalcul{
    public static void main(String[] args){
        int a;

        a = 5 * 3;
        System.out.println(a);
        a = 287 % 7;
        System.out.println(a);
        return;
    }
}

Dans ce programme on voit apparaître une variable de nom a qui est déclarée au début. Comme les valeurs qu'elle prend sont des entiers elle est dite de type entier. Le mot int2 qui précède le nom de la variable est une déclaration de type. Il indique que la variable est de type entier et ne prendra donc que des valeurs entières lors de l'exécution du programme. Par la suite, on lui affecte deux fois une valeur qui est ensuite affichée. Les résultats affichés seront 15 et 0. Dans l'opération a % b, le symbole % désigne l'opération modulo qui est le reste de la division euclidienne de a par b.

Insistons un peu sur la façon dont le programme est exécuté par l'ordinateur. Celui-ci lit les instructions du programme une à une en commençant par la fonction main, et les traite dans l'ordre où elles apparaissent. Il s'arrête dès qu'il rencontre l'instruction return;, qui est généralement la dernière présente dans une fonction. Nous reviendrons sur le mode de traitement des instructions quand nous introduirons de nouvelles constructions (itérateurs, fonctions récursives).

1.3  Types primitifs

Un type en programmation précise l'ensemble des valeurs que peut prendre une variable; les opérations que l'on peut effectuer sur une variable dépendent de son type.

Le type des variables que l'on utilise dans un programme Java doit être déclaré. Parmi les types possibles, les plus simples sont les types primitifs. Il y a peu de types primitifs: les entiers, les réels, les caractères et les booléens.

Les principaux types entiers sont int et long, le premier utilise 32 bits pour représenter un nombre; sachant que le premier bit est réservé au signe, un int fait référence à un entier de l'intervalle [-231, 231-1]. Si lors d'un calcul, un nombre dépasse cette valeur le résulat obtenu n'est pas utilisable. Le type long permet d'avoir des mots de 64 bits (entiers de l'intervalle [-263, 263-1]) et on peut donc travailler sur des entiers plus grands. Il y a aussi les types byte et short qui permettent d'utiliser des mots de 8 et 16 bits. Les opérations sur les int sont toutes les opérations arithmétiques classiques: les opérations de comparaison: égal, différent de, plus petit, plus grand et les opérations de calcul comme addition (+), soustraction (-), multiplication (*), division (/), reste (%). Dans ce dernier cas, précisons que a/b calcule le quotient de la division euclidienne de a par b et que a % b en calcule le reste. Par suite
    int q = 2/3;
contient le quotient de la division euclidienne de 2 par 3, c'est-à-dire 0.

Les types réels (en fait nombres dont le développement binaire est fini) sont float et double, le premier se contente d'une précision dite simple, le second donne la possibilité d'une plus grande précision, on dit que l'on a une double précision.

Les caractères sont déclarés par le type char au standard Unicode. Ils sont codés sur 16 bits et permettent de représenter toutes les langues de la planète (les caractères habituels des claviers des langues européennes se codent uniquement sur 8 bits). Le standard Unicode respecte l'ordre alphabétique. Ainsi le code de 'a' est inférieur à celui de 'd', et celui de 'A' à celui de 'D'.

Le type des booléens est boolean et les deux valeurs possibles sont true et false. Les opérations sont et, ou, et non; elles se notent respectivement &&, ||, !. Si a et b sont deux booléens, le résultat de a && b est true si et seulement si a et b sont tous deux égaux à true. Celui de a || b est true si et seulement si l'un de a et b est égal à true. Enfin !a est true quand a est false et réciproquement. Les booléens sont utilisés dans les conditions décrites au chapitre suivant.

La déclaration du type des variables est obligatoire en Java, mais elle peut se faire à l'intérieur d'une fonction et pas nécessairement au début. Une déclaration se présente sous la forme d'un nom de type suivi soit d'un nom de variable, soit d'une suite de noms de variables séparés par des virgules. En voici quelques exemples :
    int a, b, c;
    float x;
    char ch;
    boolean u, v;

1.4  Affectation

On a vu qu'une variable a un nom et un type. L'opération la plus courante sur les variables est l'affectation d'une valeur. Elle s'écrit :
    x = E;
E est une expression qui peut contenir des constantes et des variables. Lors d'une affectation, l'expression E est évaluée et le résultat de son évaluation est affecté à la variable x. Lorsque l'expression E contient des variables leur contenu est égal à la dernière valeur qui leur a été affectée.

Par exemple, l'affectation
    x = x + a;
consiste à augmenter la valeur de x de la quantité a.

Pour une affectation
    x = E;
le type de l'expression E et celui de la variable x doivent être les mêmes. Dans un très petit nombre de cas cette exigence n'est pas appliquée, il s'agit alors des conversions implicites de types. Les conversions implicites suivent la figure 1.1. Pour toute opération, on convertit toujours au plus petit commun majorant des types des opérandes. Des conversions explicites sont aussi possibles, et recommandées dans le doute. On peut les faire par l'opération dite de coercion (cast) suivante


Figure 1.1 : Coercions implicites.


    x = (nom-type) E;
L'expression E est alors convertie dans le type indiqué entre parenthèses devant l'expression. L'opérateur = d'affectation est un opérateur comme les autres dans les expressions. Il subit donc les mêmes lois de conversion. Toutefois, il se distingue des autres opérations par le type du résultat. Pour un opérateur ordinaire, le type du résultat est le type commun obtenu par conversion des deux opérandes. Pour une affectation, le type du résultat est le type de l'expression à gauche de l'affectation. Il faut donc faire une conversion explicite sur l'expression de droite pour que le résultat soit cohérent avec le type de l'expression de gauche.

1.5  Opérations

La plupart des opérations arithmétiques courantes sont disponibles en Java, ainsi que les opérations sur les booléens (voir chapitre suivant). Ces opérations ont un ordre de priorité correspondant aux conventions usuelles.

1.5.1  Règles d'évaluation

Les principales opérations sont +,-,*,/, % pour l'addition, soustraction, multiplication, division et le reste de la division (modulo). Il y a des règles de priorité, ainsi l'opération de multiplication a une plus grande priorité que l'addition, cela signifie que les multiplications sont faites avant les additions. La présence de parenthèses permet de mieux contrôler le résultat. Par exemple 3 + 5 * 6 est évalué à 33; par contre (3 + 5) * 6 est évalué 48. Une expression a toujours un type et le résultat de son évaluation est une valeur ayant ce type.

On utilise souvent des raccourcis pour les instructions du type
    x = x + a;
qu'on a tendance à écrire de façon équivalente, mais plus compacte :
    x += a;

1.5.2  Incrémentation et décrementation

Soit i une variable de type int. On peut l'incrémenter, c'est-à-dire lui additionner 1 à l'aide de l'instruction :
    i = i + 1;
C'est une instruction tellement fréquente (particulièrement dans l'écriture des boucles, cf. chapitre suivant), qu'il existe deux raccourcis : i++ et ++i. Dans le premier cas, il s'agit d'une post-incrémentation, dans le second d'une pré-décrémentation. Expliquons la différence entre les deux. Le code
    i = 2;
    j = i++;
donne la valeur 3 à i et 2 à j, car le code est équivalent à :
    i = 2;
    j = i;
    i = i + 1;
on incrémente en tout dernier lieu. Par contre :
    i = 2;
    j = ++i;
est équivalent quant à lui à :
    i = 2;
    i = i + 1;
    j = i;
et donc on termine avec i=3 et j=3.

Il existe aussi des raccourcis pour la décrémentation : i = i-1 peut s'écrire aussi i-- ou --i avec les mêmes règles que pour ++.

1.6  Fonctions

Le programme suivant, qui calcule la circonférence d'un cercle en fonction de son rayon, contient deux fonctions, main, que nous avons déjà rencontrée, ainsi qu'une nouvelle fonction, circonference, qui prend en argument un réel r et retourne la valeur de la circonférence, qui est aussi un réel :
// Calcul de circonférence
public class Cercle{
    static float pi = (float) Math.PI;

    public static float circonference(float r){
        return 2. * pi * r;
    }

    public static void main (String[] args){
        float c = circonference (1.5);

        System.out.println("Circonférence:  " + c);
        return;
    }
}

De façon générale, une fonction peut avoir plusieurs arguments, qui peuvent être de type différent et retourne une valeur (dont le type doit être aussi précisé). Certaines fonctions ne retournent aucune valeur. Elles sont alors déclarées de type void. C'est le cas particulier de la fonction main de notre exemple. Pour bien indiquer dans ce cas le point où la fonction renvoie la main à l'appelant, nous utiliserons souvent un return; explicite, qui est en fait optionnel. Il y a aussi des cas où il n'y a pas de paramètres lorsque la fonction effectue toujours les mêmes opérations sur les mêmes valeurs.

L'en-tête d'une fonction décrit le type du résultat d'abord puis les types des paramètres qui figurent entre parenthèses.

Les programmes que l'on a vu ci-dessus contiennent une seule fonction appelée main. Lorsqu'on effectue la commande java Nom-classe, c'est la fonction main se trouvant dans cette classe qui est exécutée en premier.

Une fonction peut appeler une autre fonction ou être appelée par une autre fonction, il faut alors donner des arguments aux paramètres d'appel.

Ce programme contient deux fonctions dans une même classe, la première fonction a un paramètre r et utilise la constante PI qui se trouve dans la classe Math, cette constante est de type double il faut donc la convertir au type float pour affecter sa valeur à un nombre de ce type.

Le résultat est fourni, on dit plutôt retourné à l'appelant par return. L'appelant est ici la fonction main qui après avoir effectué l'appel, affiche le résultat.
1
Une ligne commençant par unix% indique une commande tapée en Unix.
2
Une abréviation de l'anglais integer, le g étant prononcé comme un j français.

Précédent Remonter Suivant