Les classes sont tout d'abord des types. Ainsi, si une classe Point a été définie afin de modéliser les points du plan, il est possible de déclarer un nom dont le type est Point :
Point p;
Cette déclaration de p, qui ne crée aucun objet, dit simplement
que le nom p pourra désormais être employé pour désigner des
objets de classe Point (mais pas, par exemple, pour désigner
des chaînes de caractères). Les objets sont créés par
instanciation, en utilisant l'opérateur
new, l'un
des constructeurs de la classe, et une liste d'arguments. Par exemple,
l'expression new Point(2, 3) permet de créer un objet,
instance de la classe Point, de
coordonnées ; la valeur de cette expression est une
référence à l'objet créé et cette valeur est non nulle,
c'est-à-dire différente de la valeur null. Après l'affectation
p = new Point(2, 3);
le nom p désignera l'objet nouvellement créé
(figure ). La déclaration d'un nom d'objet peut aussi
comporter la création d'un objet ; les définitions suivantes de
p et o introduisent ces noms et les initialisent par
des références à des objets de la classe Point :
Point p = new Point(2, 3); Point o = new Point();
Un constructeur d'une classe a le même nom que la classe, et une liste de paramètres. Il peut y avoir plusieurs constructeurs, qui sont distingués par le nombre et le type de leurs paramètres. L'opérateur new, appliqué à un constructeur d'une classe, a pour effet de créer un objet, instance de cette classe, et retourne une référence vers cet objet. C'est cette référence qui est affectée, comme valeur initiale, aux noms p et o. Une référence n'est pas un objet, c'est plutôt un numéro d'identification unique, qui est géré de façon interne par la Machine Virtuelle Java, alors que les noms sont choisis et gérés par le programmeur. L'unicité signifie que chaque invocation d'un constructeur retourne une référence à un objet différent. Malgré les apparences, les deux points suivants sont différents, et le test d'égalité p1 == p2 aura pour valeur false :
Point p1 = new Point(2, 3); Point p2 = new Point(2, 3);
![]() |
Il est préférable de dire que p « désigne » un point, ou «
réfère » à tel point, plutôt que de dire qu'il « est » un point.
D'ailleurs, l'opération d'affectation permet de remplacer le point
désigné par un autre. Après l'affectation suivante, les deux noms
p1 et p2 désigneront le même point, celui référencé par
p1 (figure ):
p2 = p1;
package geometrie; class Point { double x, y; // ... }
Les champs sont d'abord initialisés à la
valeur nulle de leur type. Ces valeurs nulles sont 0 pour les
types numériques, false pour le type boolean,
'\u0000'
pour le type char, et null pour les
références à des objets (tableaux et instances).
On accède à un champ d'une instance en suffixant le nom d'un objet par le nom du champ ; par exemple, on accède aux champs x et y du point p au moyen des expressions p.x et p.y. C'est une erreur d'accéder à un champ d'un objet qui n'existe pas. Ainsi, l'évaluation de p.x, qui suit une déclaration de p et son initialisation par null, provoque le déclenchement de l'exception NullPointerException :
Point p = null; p.x = 2; // ERREUR -> NullPointerException
Pour éviter cette erreur, il est souvent nécessaire de commencer par faire le test p != null, avant d'accéder à un champ.
package geometrie; class Point { // ... // les deux constructeurs : Point() {} Point(double x, double y) { this.x = x; this.y = y; } // ... }
Employé dans un constructeur, le nom this réfère à l'instance créée par ce constructeur. Ceci permet en particulier d'employer le nom du champ x comme paramètre du constructeur, dans this.x = x.
Il n'est pas obligatoire de définir des constructeurs. Si l'on n'en définit pas explicitement, le constructeur sans paramètre et de corps vide est toujours défini implicitement : c'est le constructeur par défaut. Par contre, dès que l'on définit un (autre) constructeur, ce constructeur par défaut n'est plus défini implicitement et ne peut donc plus être utilisé. C'est pourquoi, il faut ici définir explicitement le constructeur par défaut, du moins si l'on envisage de l'utiliser.
Point p = null; p.translater(1, 2); // ERREUR -> NullPointerException
Voici enfin la définition de la classe Point, qui comprend deux champs, deux constructeurs et une méthode :
package geometrie; class Point { double x, y; Point() {} Point(double x, double y) { this.x = x; this.y = y; } void translater(double dx, double dy) { this.x = this.x + dx; // x = x + dx this.y = this.y + dy; // y = y + dy } }
Si cette classe est destinée à être utilisée dans d'autres applications, on doit la déclarer publique et faire de même pour les membres et les constructeurs que l'on veut rendre utilisables ; par exemple, on peut exporter les deux constructeurs et la méthode translater mais pas les deux champs x et y :
package geometrie; public class Point { double x, y; public Point() {} public Point(double x, double y) { this.x = x; this.y = y; } public void translater(double dx, double dy) { this.x = this.x + dx; // x = x + dx this.y = this.y + dy; // y = y + dy } }
D'autre part, le nom this() peut être employé avec une liste d'arguments, mais seulement en première instruction du corps d'un constructeur, pour invoquer explicitement un autre constructeur de la classe. Par exemple, le constructeur sans argument pourrait être défini à l'aide du constructeur à deux arguments en invoquant this(0,0) :
Point() { this(0, 0); }