Apprendre à Programmer en Java pour un Débutant

Java est un langage de programmation moderne développé par Sun Microsystems (aujourd'hui racheté par Oracle). Il ne faut surtout pas le confondre avec JavaScript (langage de scripts utilisé principalement sur les sites web), car Java n'a rien à voir. Une de ses plus grandes forces est son excellente portabilité : une fois votre programme créé, il fonctionnera automatiquement sous Windows, Mac, Linux, etc.

Introduction au langage Java

Le langage Java est un langage généraliste de programmation synthétisant les principaux langages existants lors de sa création en  par Sun Microsystems. Il permet une programmation orientée-objet (à l’instar de SmallTalk et, dans une moindre mesure, C++), modulaire (langage ADA) et reprend une syntaxe très proche de celle du langage C.

Outre son orientation objet, le langage Java a l’avantage d’être modulaire (on peut écrire des portions de code génériques, c-à-d utilisables par plusieurs applications), rigoureux (la plupart des erreurs se produisent à la compilation et non à l’exécution) et portable (un même programme compilé peut s’exécuter sur différents environnements). En contre-partie, les applications Java ont le défaut d’être plus lentes à l’exécution que des applications programmées en C par exemple.

Environnement de Java

Java est un langage interprété, ce qui signifie qu’un programme compilé n’est pas directement exécutable par le système d’exploitation mais il doit être interprété par un autre programme, qu’on appelle interpréteur.

Un programmeur Java écrit son code source, sous la forme de classes, dans des fichiers dont l’extension est .java. Ce code source est alors compilé par le compilateur javac en un langage appelé bytecode et enregistre le résultat dans un fichier dont l’extension est .class. Le bytecode 1 Chapitre 1. Introduction au langage Java ainsi obtenu n’est pas directement utilisable.

Il doit être interprété par la machine virtuelle de Java qui transforme alors le code compilé en code machine compréhensible par le système d’exploitation. C’est la raison pour laquelle Java est un langage portable : le bytecode reste le même quelque soit l’environnement d’exécution, Sun Microsystems est racheté par Oracle Corporation qui fournit dorénavant les outils de développement Java SE (Standard Edition) contenus dans le Java Development Kit (JDK). Au moment où est écrit ce livret, la dernière version stable est le JDK 

Compilation de Java

La compilation s’effectue par la commande javac suivie d’un ou plusieurs nom de fichiers contenant le code source de classes Java. Par exemple, javac MyProg.java compile la classe MyProg dont le code source est situé dans le fichier MyProg.java. La compilation nécessite souvent la précision de certains paramètres pour s’effectuer correctement, notamment lorsque le code source fait référence à certaines classes situées dans d’autres répertoires que celui du code compilé. Il faut alors ajouter l’option -classpath suivie des répertoires (séparés par un ; sous Windows et : sous Unix) des classes référencées. Par exemple : javac -classpath /prog/exos1:/cours MyProg.java

compilera le fichier MyProg.java si celui-ci fait référence à d’autres classes situées dans les répertoires /prog/exos1 et /cours. Le résultat de cette compilation est un fichier nommé MyProg.class contenant le bytecode correspondant au source compilé. Ce fichier est créé par défaut dans le répertoire où la compilation s’est produite. Il est cependant fortement souhaitable de ne pas mélanger les fichiers contenant le code source et ceux contenant le bytecode. Un répertoire de destination où sera créé le fichier MyProg.class peut être précisé par l’option -d, par exemple : javac -d /prog/exos1 -classpath /cours MyProg.java

Interprétation de Java

Le bytecode obtenu par compilation ne peut être exécuté qu’à l’aide de l’interpréteur. L’exécution s’effectue par la commande java suivie du nom de la classe à exécuter (sans l’extension .class). Comme lors de la compilation, il se peut que des classes d’autres répertoires soient nécessaires. Il faut alors utiliser l’option -classpath comme dans l’exemple qui suit : java -classpath /prog/exos1:/cours MyProg

Programmation orientée-objet

Chaque langage de programmation appartient à une “famille” de langages définissant une approche ou une méthodologie générale de programmation. Par exemple, le langage C est un langage de programmation procédurale car il suppose que le programmeur s’intéresse en priorité aux traitements que son programme devra effectuer. Un programmeur C commencera par identifier ces traitements pour écrire les fonctions qui les réalisent sur des données prises comme paramètres d’entrée.

La programmation orientée-objet (introduite par le langage SmallTalk) propose une méthodologie centrée sur les données. Le programmeur Java va d’abord identifier un ensemble d’objets, tel que chaque objet représente un élément qui doit être utilisé ou manipulé par le programme, sous la forme d’ensembles de données. Ce n’est que dans un deuxième temps, que le programmeur va écrire les traitements, en associant chaque traitement à un objet donné. Un objet peut être vu comme une entité regroupant un ensemble de données et de méthodes(l’équivalent d’une fonction en C) de traitement.

Classe dans Java

Un objet est une variable (presque) comme les autres. Il faut notamment qu’il soit déclaré avec son type. Le type d’un objet est un type complexe (par opposition aux types primitifs entier, caractère, …) qu’on appelle une classe. Une classe regroupe un ensemble de données (qui peuvent être des variables primitives ou des objets) et un ensemble de méthodes de traitement de ces données et/ou de données extérieures à la classe. On parle d’encapsulation pour désigner le regroupement de données dans une classe.

Par exemple, une classe Rectangle utilisée pour instancier des objets représentant des rectangles, encapsule  entiers : la longueur et la largeur du rectangle ainsi que la position en abscisse et en ordonnée de l’origine du rectangle (par exemple, le coin en haut à gauche). On peut alors imaginer que la classe Rectangle implémente une méthode permettant de déplacer le rectangle qui nécessite en entrée deux entiers indiquant la distance de déplacement en abscisse et en ordonnée. L’accès aux positions de l’origine du rectangle se fait directement (i.e. sans passage de paramètre) lorsque les données sont encapsulées dans la classe où est définie la méthode. Un exemple, écrit en Java, de la classe Rectangle est donné ci-dessous :

class Rectangle { int longueur ; int largeur ; int origine_x ; int origine_y ; void deplace(int x, int y) { this.origine_x = this.origine_x + x ; this.origine_y = this.origine_y + y ; } int surface() { return this.longueur * this.largeur ; } }

Pour écrire un programme avec un langage orienté-objet, le programmeur écrit uniquement des classes correspondant aux objets de son système. Les traitements à effectuer sont programmés dans les méthodes de ces classes qui peuvent faire appel à des méthodes d’autres classes. En général, on définit une classe, dite “exécutable”, dont une méthode peut être appelée pour exécuter le programme.

Encapsulation dans Java

Lors de la conception d’un programme orienté-objet, le programmeur doit identifier les objets et les données appartenant à chaque objet mais aussi des droits d’accès qu’ont les autres objets sur ces données. L’encapsulation de données dans un objet permet de cacher ou non leur existence aux autres objets du programme. Une donnée peut être déclarée en accès :

  • public : les autres objets peuvent accéder à la valeur de cette donnée ainsi que la modifier ;
  • privé : les autres objets n’ont pas le droit d’accéder directement à la valeur de cette donnée (ni de la modifier). En revanche, ils peuvent le faire indirectement par des méthodes de l’objet concerné (si celles-ci existent en accès public).

Méthode constructeur de Java

Chaque classe doit définir une ou plusieurs méthodes particulières appelées des constructeurs. Un constructeur est une méthode invoquée lors de la création d’un objet. Cette méthode, qui peut être vide, effectue les opérations nécessaires à l’initialisation d’un objet. Chaque constructeur doit avoir le même nom que la classe où il est défini et n’a aucune valeur de retour (c’est l’objet créé qui est renvoyé). Dans l’exemple précédent de la classe rectangle, le constructeur initialise la valeur des données encapsulées : class Rectangle { ... Rectangle(int lon, int lar) { this.longueur = lon ; this.largeur = lar ; this.origine_x = 0 ; this.origine_y = 0 ; } ... } 

Plusieurs constructeurs peuvent être définis s’ils acceptent des paramètres d’entrée différents.

Objet dans Java - Instanciation

Un objet est une instance (anglicisme signifiant « cas » ou « exemple ») d’une classe et est référencé par une variable ayant un état (ou valeur). Pour créer un objet, il est nécessaire de déclarer une variable dont le type est la classe à instancier, puis de faire appel à un constructeur de cette classe. L’exemple ci-dessous illustre la création d’un objet de classe Cercle en Java : Cercle mon_rond ; mon_rond = new Cercle();

L’usage de parenthèses à l’initialisation du vecteur, montre qu’une méthode est appelée pour l’instanciation. Cette méthode est un constructeur de la classe Cercle. Si le constructeur appelé nécessite des paramètres d’entrée, ceux-ci doivent être précisés entre ces parenthèses (comme lors d’un appel classique de méthode). L’instanciation d’un objet de la classe Rectangle faisant appel au constructeur donné en exemple ci-dessous pourra s’écrire : Rectangle mon_rectangle = new Rectangle(15,5);

Remarque importante : en Java, la notion de pointeur est transparente pour le programmeur. Il faut néanmoins savoir que toute variable désignant un objet est un pointeur. Il s’ensuit alors que le passage d’objets comme paramètres d’une méthode est toujours un passage par référence. A l’inverse, le passage de variables primitives comme paramètres est toujours un passage par valeur.

Accès aux variables et aux méthodes

Pour accéder à une variable associée à un objet, il faut préciser l’objet qui la contient. Le symbole ’.’ sert à séparer l’identificateur de l’objet de l’identificateur de la variable. Une copie de la longueur d’un rectangle dans un entier temp s’écrit : int temp = mon_rectangle.longueur ;

La même syntaxe est utilisée pour appeler une méthode d’un objet. Par exemple : mon_rectangle.deplace(10,-3);

Pour qu’un tel appel soit possible, il faut que trois conditions soient remplies : . La variable ou la méthode appelée existe ! . Une variable désignant l’objet visé existe et soit instanciée. . L’objet, au sein duquel est fait cet appel, ait le droit d’accéder à la méthode ou à la variable.

Pour référencer l’objet “courant” (celui dans lequel se situe la ligne de code), le langage Java fournit le mot-clé this. Celui-ci n’a pas besoin d’être instancié et s’utilise comme une variable désignant l’objet courant. Le mot-clé this est également utilisé pour faire appel à un constructeur de l’objet courant. Ces deux utilisations possibles de this sont illustrées dans l’exemple suivant :class Carre { int cote ; int origine_x ; int origine_y ; Carre(int cote, int x, int y) { this.cote = cote ; this.origine_x = x ; this.origine_y = y ; } Carre(int cote) { this(cote, 0, 0); } }