Toutes les variables que l'on peut manipuler en Java sont typées, ce qui signifie que le programmeur doit leur affecter un type qui est pris en compte par le compilateur pour vérifier la cohérence de l'utilisation de ces variables. On distingue deux grandes catégories de types:
String s; // N'alloue pas l'espace mémoire requis // pour stocker un objet de la classe String s = new String("toto"); // L'opérateur new alloue l'espace mémoire requis par le // constructeur de la classe String et renvoie (assigne // dans la variable s) la référence à cet espace mémoire.On distingue quelquefois les références à des objets (comme ci-dessus) et les références à des tableaux. Ces deux types de références sont bien de même nature, même si les constructeurs de tableaux sont un peu particuliers.
Les tableaux, en Java, sont des instances de classes invisibles (leur documentation n'apparaît pas dans les API). Ils permettent de stocker un nombre établi d'éléments, tous du même type. Une variable de type tableau se déclare avec la syntaxe suivante:
TypeElement[] nomVariable;Un objet tableau de ce type, de taille N, s'alloue comme ceci:
nomVariable = new TypeElement[N];Il existe d'autres syntaxes, mais celle-ci est la plus répandue.
Lorsqu'un tableau est alloué, tous ses éléments sont initialisés à la valeur par défaut du type des éléments. Cette valeur est 0 pour tous les types numériques, false pour le type boolean et null pour tous les types référence. Ce null correspond à « la référence vers rien » et c'est une erreur que d'essayer d'y accéder.
Étant donnée une instance de tableau tab, la taille de ce tableau peut être obtenue par l'expression tab.length.
Écrire un programme qui accepte, sur la ligne de commande, un nombre arbitraire de valeurs entières et qui affiche la moyenne de ces valeurs.
Écrire une méthode d'affichage des éléments d'un tableau d'entiers de taille quelconque. Écrire une méthode d'initialisation d'un tableau qui affecte à chaque indice le carré de cet indice (tab[5] = 25). Écrire un programme qui prend en argument sur la ligne de commande un entier n, définit un tableau tab de n entiers, l'initialise et l'affiche à l'aide des fonctions précédentes.
Écrire une fonction tri() qui trie un tableau d'entiers dans l'ordre croissant.
Écrire un programme qui accepte une liste d'entiers sur la ligne de commande, les place dans un tableau d'entiers créé pour l'occasion et les affiche dans l'ordre après avoir trié ce tableau à l'aide de tri(). Exemple:
% java Tri 34 65 12 7 27 12 7 12 12 27 34 65
Même question pour un tableau de double, avec une fonction de même nom tri().
Le mécanisme des exceptions permet de séparer le flot de contrôle classique (appel/retour de fonction) du flot de contrôle lié à un comportement exceptionnel, tel qu'une erreur dépendant du contexte d'exécution.
Par exemple, revenons quelques instants au programme seance1.BaseDeux qui attend, sur la ligne de commande, qu'un entier soit fourni. Lorsqu'un tel entier est fourni, tout se passe bien:
% java seance1.BaseDeux 9 1001Si le programme est appelé sans aucun argument sur la ligne de commande, voici l'affichage produit:
% java seance1.BaseDeux Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at seance1.BaseDeux.main(BaseDeux.java:15)En effet, la ligne 15 du programme source seance1/BaseDeux.java contient l'instruction suivante:
int argument = Integer.parseInt(args[0]);or, puisqu'aucun argument n'a été spécifié sur la ligne de commande, le tableau args ne contient aucun élément. L'accès au premier élément de ce tableau, args[0], provoque donc une erreur représentée par la levée d'une exception de la classe ArrayIndexOutOfBoundsException. Remarquons que si un argument est fourni mais n'est pas un entier, alors l'exception levée représente le fait qu'il n'est pas possible d'y lire un entier:
% java seance1.BaseDeux toto Exception in thread "main" java.lang.NumberFormatException: For input \ string: "toto" at java.lang.NumberFormatException.forInputString(Number \ FormatException.java:48) at java.lang.Integer.parseInt(Integer.java:426) at java.lang.Integer.parseInt(Integer.java:476) at seance1.BaseDeux.main(BaseDeux.java:15)
Les exceptions représentent donc des problèmes qui arrivent au cours de l'exécution d'un programme. Leur cycle de vie est le suivant.
Il est possible d'ajouter un bloc finally après un bloc try/catch. Ce bloc sera exécuté dans tous les cas.
Lorsqu'une exception peut être propagée par une fonction, cette fonction peut déclarer ce risque de propagation par le mot-clef throws. Par exemple, en l'absence des blocs de capture, nous aurions pu déclarer dans BaseDeux.java:
public static void main(String[] args) throws ArrayIndexOutOfBoundsException, NumberFormatException { // ... }Nous verrons qu'il existe différents sous-types d'exceptions. Retenons pour l'instant que le compilateur exige que, pour certains types, les exceptions soient soit capturées, soit déclarées par une clause throws. Ce n'est pas le cas des exceptions les plus courantes que nous avons rencontrées jusqu'ici.
Modifier le programme seance1.BaseDeux pour qu'il ait le comportement suivant:
% java seance1.BaseDeux 9 1001 % java seance1.BaseDeux Il faut donner un entier décimal en argument % java seance1.BaseDeux toto L'argument fourni doit être entier
La programmation objet, c'est à dire celle qu'on est sensé
mettre en oeuvre lorsqu'on écrit des programmes avec un langage à
objet (ou langage orienté objet) tel que Java, fait
intervenir différents concepts tels que celui de classe,
d'objet, de responsabilité, d'encapsulation,
etc.
Le premier concept auquel on est confronté lorsqu'on écrit un
programme est celui de classe: le mot-clé class, dans
class MaClasse { ... }permet de définir (entre les accolades) les membres de la classe MaClasse. Les membres sont principalement les méthodes (quelques fois appelées fonctions) et les champs (aussi appelés attributs).
Brouette b = new Brouette(); Personne bob = new Personne("Robert"); jean.discuterAvec(b); // Erreur de compilation jean.discuterAvec(bob); // CorrectDans la dernière instruction, la méthode discuterAvec est appelée sur l'objet jean (qu'on appelle la cible ou le receveur de la méthode) avec comme argument l'objet bob.
Nous considérons ici la classe Point des objets qui sont des points dans un plan à deux dimensions. Les instances de cette classe disposent donc, pour décrire leur état, de deux champs, x et y, de type double.
Pour créer un point, on dispose d'un constructeur qui accepte les deux coordonnées du point que l'on veut créer.
Un constructeur est une méthode un peu particulière puisqu'il doit avoir exactement le nom de la classe (avec sa majuscule) et qu'il n'a pas de type de retour (en effet, lorsqu'un tel constructeur est associé à l'opérateur new, il retourne la référence de l'objet (l'instance) qui vient d'être alloué et celle-ci est donc typée Point dans notre exemple.
Par ailleurs, on souhaite pouvoir effectuer deux opérations sur n'importe quel point:
Point p1 = new Point(); Point p2 = new Point(); System.out.println(p1 == p2);L'opérateur == agit en général sur les types primitifs. Lorsqu'il est utilisé sur des références à des objets, il teste l'égalité des références aux objets. En d'autre termes, il teste les valeurs qui ont été retournées par des appels à l'opérateur new. En ce sens, les deux points p1 et p2 qui ont été créés correspondent à deux références différentes, même si elles réfèrent des objets identiques (leur état est identique).
Surchargez, dans la classe Point, la méthode public
void translate(double dx, double dy) avec une méthode public
void translate(double d) qui déplace à la fois x et
y de la valeur d. Testez cette méthode.
Tout comme les constructeurs, les méthodes
peuvent être surchargées: cela signifie que plusieurs méthodes ayant
le même nom cohabitent dans la même classe. Elle doivent se distinguer
par des listes de paramètres différents.
Attention: dans une classe, deux méthodes ne peuvent pas avoir
le même nom et les même paramètres, même si elles ont des types de
retour différents.