
FAQ Langage JavaConsultez toutes les FAQ
Nombre d'auteurs : 42, nombre de questions : 297, derni�re mise � jour : 19 septembre 2017 Ajouter une question
Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur le forum Java de http://java.developpez.com ainsi que l'exp�rience personnelle des auteurs.
Nous tenons � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant r�dacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Qu'est-ce qu'une classe ?
- Qu'est-ce qu'un package ?
- Qu'est-ce que l'h�ritage ?
- Qu'est-ce qu'une classe abstraite ?
- Qu'est-ce qu'une classe interne ?
- Quels sont les diff�rents types de classes internes ?
- Qu'est-ce qu'une interface ?
- Qu'est-ce que la s�rialisation ?
- Quelles sont les r�gles � respecter pour red�finir/impl�menter une m�thode ?
- Qu'est-ce que la surcharge des m�thodes ?
- Qu'est-ce qu'un getter ?
- Qu'est-ce qu'un setter ?
- Qu'est-ce que les Generics (types param�tr�s) ?
- Qu'est-ce que l'auto-boxing/auto-unboxing ?
- Qu'est-ce qu'une annotation ?
- Qu'est-ce qu'une enum (type �num�r�) ?
- Qu'est-ce qu'une constante ?
- Qu'est-ce qu'un membre � synthetic � ?
- Qu'est-ce qu'une m�thode � bridge � ?
- Comment sp�cifier qu'un param�tre doit impl�menter plusieurs interfaces ?
- Qu'est-ce qu'une interface fonctionnelle ?
- Qu'est-ce qu'un lambda ?
- Qu'est-ce qu'une r�f�rence de m�thode ?
- Qu'est-ce qu'une m�thode par d�faut (Defender Method) ?
- Qu'est-ce qu'un objet immuable ?
- Java est-il Little-Endian ou Big-Endian ?
- Qu'est-ce qu'un singleton ?
- Pourquoi et comment red�finir la m�thode equals() ?
- Pourquoi et comment red�finir la m�thode hashCode() ?
- Qu'est-ce qu'un POJO ?
- Comment copier un objet ?
- Comment cloner un objet ?
- Comment cloner un objet en profondeur ?
Une classe est constitu�e�:
- de donn�es, ce qu'on appelle des attributs ou membres�;
- de proc�dures et/ou des fonctions, ce qu'on appelle des m�thodes.
Une classe est un mod�le de d�finition pour des objets�:
- ayant m�me structure (m�me ensemble d'attributs)�;
- ayant m�me comportement (m�mes m�thodes)�;
- ayant une s�mantique commune.
Les objets sont des repr�sentations dynamiques, du mod�le d�fini pour eux au travers de la classe (instanciation)�:
- une classe permet g�n�ralement d'instancier (cr�er) plusieurs objets�;
- chaque objet est instance d'une classe et une seule.
La classe suivante contient trois attributs (puissance, estDemarre et vitesse). Elle dispose �galement d'un s�lecteur (deQuellePuissance) et de modificateurs (demarre et accelere)�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Voiture { private int puissance; private boolean estDemarree; private double vitesse; public int deQuellePuissance() { return puissance; } public void demarre() { estDemarree = true; } public void accelere(double v) { if (estDemarree) { vitesse = vitesse + v } } } |
Un package ou paquetage est un moyen d'organiser les classes de votre code. Cette unit� organisationnelle est � rapprocher du m�canisme des espaces de nommage (naming space) qui existe dans d'autres langages m�me si les packages fonctionnent un peu diff�remment.
En Java, un package correspond toujours � un ou plusieurs r�pertoires ayant exactement le m�me nom, situ�s sur le disque, dans une ou plusieurs archives JAR ou plus g�n�ralement sur le CLASSPATH. Les classes qui sont d�clar�es comme appartenant � ce package doivent �tre physiquement situ�es dans un de ces r�pertoires.
Un package est identifi� par son nom court (le nom du r�pertoire lui-m�me) mais c'est surtout son nom long qui le rend unique. Le nom long ou nom complet est constitu� du cheminement complet des noms de tous les packages interm�diaires depuis la racine du CLASSPATH jusqu'au r�pertoire final, s�par�s par des points (.). Par exemple, si nous avons un r�pertoire d situ� dans l�arborescence suivante�:
Code Texte : | S�lectionner tout |
1 2 3 4 | a ∟ b ∟ c ∟ d |
le package final aura pour pour nom court d, mais son nom long est a.b.c.d. Tous les �l�ments contenus dans ce r�pertoire font partie du package a.b.c.d. Si nous retrouvons exactement la m�me arborescence ailleurs sur le CLASSPATH, alors les �l�ments de ce second r�pertoire feront �galement partie du package a.b.c.d.
S'il existe un autre package nomm� d, mais dont le nom long est diff�rent, par exemple a.b.e.f.g.d), alors il ne s'agit pas du m�me package puisque l'arborescence des r�pertoires est totalement diff�rente�!
D�claration
Il nous faut donc une arborescence de r�pertoire d�crivant le package. Quand une classe est �crite dans ce package, son ent�te doit obligatoirement d�buter par�:
Code Java : | S�lectionner tout |
package <nom long du package>;
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | package a.b.c.d; public class Voiture { // D�claration du reste de la classe. [...] |
Cette classe a pour nom court Voiture, mais pour nom long ou nom complet a.b.c.d.Voiture.
Le code de la classe ne compilera pas si la d�claration du package dans l�ent�te ne correspond pas au chemin des r�pertoires dans lesquels se trouve le fichier source.
Package sans nom
La racine de l'arborescence des packages ne porte pas de nom, on dit qu'il s'agit du package sans nom ou package par d�faut. Il peut �tre difficile de r�f�rencer des classes ou des ressources qui sont plac�es sur le package racine�; il est donc recommand� de ne pas l'utiliser.
Nommage
Par d�faut, le nom des packages est limit� par l'ensemble des caract�res commun�ment admis pour nommer des r�pertoires dans un syst�me de fichiers. De plus, il est impossible d'utiliser le symbole - tandis que le symbole _ est admis. Le nom court d'un package ne peut pas non plus d�buter par un chiffre (mais on peut trouver des chiffres � des positions ult�rieures). La casse (majuscules/minuscules) utilis�e dans l��criture du nom des packages et des r�pertoires est importante.
Par convention, on �crit le nom des packages en minuscules.
Il existe de plus quelques r�gles et interdictions concernant l'API Java standard�:
- les packages dont l'arborescence commence par java sont r�serv�s � l�impl�mentation de l'API standard dans la JVM (ce qui inclut les classes de base, les collections, AWT, etc.)�;
- les packages dont l'arborescence commence par javax sont r�serv�s au m�canisme des extensions standard de l'API Java (ce qui inclut Swing, l'API d'impression, l'API XML, etc.)�;
- les packages dont l'arborescence commence par javafx sont r�serv�s au toolkit JavaFX.
Vous devez absolument �viter de les utiliser.
De la m�me mani�re, vous devez �viter d'utiliser une arborescence de package qui pourrait d�j� �tre prise par un projet pr�existant ou une biblioth�que tierce sous peine de conflit dans les d�finitions de vos classes.
De mani�re � cr�er des arborescences de stockage de classes uniques, Sun Microsystems, puis Oracle Corporation sugg�rent aux entreprises et organisations d'utiliser le chemin inverse de celui de leur nom de domaine. Par exemple, Oracle utilise r�guli�rement les noms de package com.sun et com.oracle pour la base des arborescences de ses projets. De mani�re similaire, un projet Java d�velopp� par l��quipe de D�veloppez dont le site est disponible sur l'URL http://java.developpez.com pourrait tr�s bien utiliser le nom de package com.developpez.java pour son arborescence.
Pour les particuliers, vous pouvez utiliser votre adresse m�l, votre nom de famille ou encore votre surnom/avatar dans des jeux en ligne ou des r�seaux sociaux pour composer la base de votre package personnel. Par exemple�: com.monfournisseur.dupont74.jean.
Acc�s
Pour acc�der aux classes d'un package, il existe deux solutions�:
- il suffit d��crire le nom complet (ou nom long) de la classe � chaque endroit o� ce type est utilis�. Par exemple�:
Code Java : S�lectionner tout a.b.c.d.Voiture maVoiture = new a.b.c.d.Voiture();
- on peut utiliser une directive import pour que le compilateur accepte d'utiliser le nom court de la classe. Par exemple �:
Code Java : S�lectionner tout 1
2
3
4
5import a.b.c.d.Voiture; [...] Voiture maVoiture = new Voiture();
Il est �galement possible d�utiliser la syntaxe large (wildcard) en utilisant le caract�re �toile (*). Par exemple�:Code Java : S�lectionner tout 1
2
3
4
5import a.b.c.d.*; [...] Voiture maVoiture = new Voiture();
Cela permet, non seulement d'utiliser le nom court de la classe Voiture, mais �galement celui de toutes les autres classes disponibles dans le package a.b.c.d. � la compilation, le compilateur cherchera � remplacer les noms courts par les noms longs appropri�s. Des erreurs seront g�n�r�es en cas d�ambig�it�.
Note�: il n'y a pas besoin d'importer les classes du package java.lang. �tant donn� qu'il s'agit des classes de base au c�ur de l'API Java, ce package est automatiquement import� de mani�re implicite. Ainsi, il n'y a pas lieu de faire�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | import java.lang.System; [...] System.out.println("Salut�!"); |
Ou�:
Code Java : | S�lectionner tout |
java.lang.System.out.println("Salut�!");
On peut directement �crire � la place�:
Code Java : | S�lectionner tout |
System.out.println("Salut�!");
Conflits
En cas de conflit dans le nom d'une classe, il n'est plus possible de proc�der � des importations. Pour r�soudre l�ambig�it�, il suffit de se forcer � utiliser le nom complet de la classe. Par exemple�:
Code Java : | S�lectionner tout |
1 2 | java.util.Date uneDateJava = [...] java.sql.Date uneDateSQL = [...] |
Ici, �tant donn� que nous avons utilis� le nom complet des classes, il n'y a pas d�ambig�it� entre les classes java.util.Date et java.sql.Date. Un package sert donc � identifier une classe de mani�re unique. Ainsi, des classes portant le m�me nom, mais plac�es dans des packages diff�rents ne sont pas la m�me classe�: java.util.Date et java.sql.Date sont deux classes bien distinctes�!
Attention�: importer un package, n'importe pas automatiquement ses sous-packages. Un sous-package est totalement ind�pendant de son package parent. On fera donc�:
Code Java : | S�lectionner tout |
1 2 3 4 | import a; import a.b; import a.b.c; import a.b.c.d; |
L'h�ritage est un des principaux concepts de la programmation orient�e objet. L'h�ritage permet de d�finir une relation de ��filiation�� entre classes. Ainsi une classe fille (ou sous-classe) �tend une classe m�re (ou super-classe). L'h�ritage permet en g�n�ral de sp�cialiser une classe.
Pour indiquer qu'une classe h�rite d'une autre, il faut utiliser le mot-cl� extends�:
Code Java : | S�lectionner tout |
1 2 3 | public class Fille extends Mere{ // Ici, le code sp�cifique de la classe fille. } |
L'h�ritage implique plusieurs choses.
La fille h�rite du type de la m�re
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class Couleur(){ String nom; public Couleur(String nom){ this.nom = nom; } } public class Rouge extends Couleur{ public Rouge(){ super("rouge"); } } public class AutreClasse(){ public void setCouleur(Couleur uneCouleur){ [...] } public static void main(String[] args){ AutreClasse ac = new AutreClasse(); ac.setCouleur(new Couleur("vert")); ac.setCouleur(new Rouge()); } } |
Ici, la classe Rouge �tend la classe Couleur, cela signifie qu'une instance de la classe Rouge est �galement une instance de la classe Couleur. Il est donc possible de passer une instance de la classe Rouge en param�tre d'une m�thode qui accepte une instance de la classe Couleur.
La fille h�rite de plusieurs attributs, m�thodes et constructeurs de la m�re
L'acc�s � ces attributs ou m�thodes se fait avec le mot-cl� super. Voici comment est d�finie l'accessibilit� aux composantes de la super-classe, en fonction des modificateurs�:
Mot-cl� | Acc�s |
public | Oui |
Oui, seulement si la classe fille se trouve dans le m�me package que la super-classe. | |
protected | Oui, quel que soit le package de d�finition de la classe fille. |
private | Non. |
Une classe abstraite est une classe incompl�te. Elle regroupe un ensemble de variables et de m�thodes, mais certaines de ses m�thodes ne contiennent pas d'instruction, elles devront �tre d�finies dans une classe h�ritant de cette classe abstraite. Une classe abstraite doit �tre marqu�e du mot-cl� abstract.
Toute m�thode d�clar�e abstraite, doit �galement �tre marqu�e du mot-cl� abstract et ne doit pas avoir de corps. L�impl�mentation de ces m�thodes est laiss�e aux soins des classes filles de cette classe.
Une classe qui contient au moins une m�thode abstraite ou qui h�rite d'une classe abstraite et n�impl�mente aucune des m�thodes abstraites de sa classe m�re doit obligatoirement �tre elle-m�me marqu�e du mot-cl� abstract.
� quoi �a sert�?
En g�n�ral, cela sert � d�finir les grandes lignes du comportement d'une classe d'objets sans forcer l'impl�mentation des d�tails de l'algorithme. Prenons l'exemple d'une cha�ne de montage automobile, laquelle sort un mod�le de voiture particulier. On peut choisir de faire une nouvelle cha�ne de montage pour le mod�le � pare-chocs m�tallis�s, une pour le mod�le � pare-chocs en plastique, etc. Ou on peut d�cider de faire une cha�ne de montage g�n�rique, de laquelle sortiront des v�hicules non finis, que l'on terminera sur d'autres petites cha�nes.
Comment �a marche�?
Comme indiqu� ci-dessus, une classe abstraite est incompl�te, elle ne peut donc pas �tre instanci�e et doit �tre h�rit�e. Certaines classes abstraites disposeront de m�thodes abstraites (que les classes enfants devront impl�menter). Voici un exemple de d�claration�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | /** La classe abstraite employ�e�: */ public abstract class Employe { [...] /** d�finition d'une m�thode abstraite * on notera qu'il n'y a pas d'instruction et un point-virgule � la fin */ public abstract void licencier(); } |
Ici, la classe Employe est abstraite et d�clare une m�thode abstraite nomm�e licencier().
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // Class Ouvrier public class Ouvrier extends Employe { // d�finition du code de licencier @Override public void licencier() { // On d�finit le code. System.out.println("Dehors�!"); } } // Class Patron public class Patron extends Employe { // D�finition du code de la m�thode licencier. @Override public void licencier() { System.out.println("Veuillez comprendre que dans la conjoncture actuelle ...�!"); } } |
Ici, les classes Ouvrier et Patron h�ritent toutes les deux de la classe Employe. Comme ces deux classes ne sont pas abstraites, elles doivent chacune d�finir la m�thode licencier() et chacune dispose d'une impl�mentation diff�rente.
Il est �galement possible d'instancier une classe abstraite directement en cr�ant une classe anonyme qui impl�mente les m�thodes d�clar�es abstraites dans sa classe m�re. Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 | Employe bob = new Employe() { @Override public void licencier() { System.out.println("Cherche un nouveau boulot."); } }; |
Ici, nous avons cr�� une nouvelle classe anonyme qui h�rite de la classe Employe.
Note�: lorsqu'une classe fille impl�mente une m�thode d�finie dans une classe abstraite, on peut pr�c�der cette m�thode de l'annotation @Override.
Une classe interne (ou nested class) est une classe d�clar�e � l'int�rieur d'une autre classe. Elle poss�de les m�mes possibilit�s qu'une autre classe, mais elle est toujours d�pendante de sa classe conteneur et ne peut �tre utilis�e que par la classe conteneur.
Classe interne
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 | class Outer { class Inner { } } |
Ici Inner est une classe interne � la classe Outer.
Une classe interne peut acc�der de mani�re transparente aux membres de l'instance de la classe dont elle fait partie. Par exemple dans ce code�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | class Outer{ int i = 100; class Inner { int k = i; } } |
Une classe interne ne peut par contre pas comporter de contexte statique.
Classe interne statique
On peut aussi d�clarer une classe interne statique, ce qui fait qu'elle ne sera plus li�e � l'instance de la classe conteneur et qu'elle pourra d�clarer des contextes statiques.
Code Java : | S�lectionner tout |
1 2 3 4 | class Outer { static class Inner { } } |
Mais elle ne pourra plus utiliser les variables d'instance de la classe conteneur, mais seulement les variables de classe (statiques). Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | class Outer { static int i = 100; static class Inner { int k = i; } } |
Une classe interne est une classe qui est d�clar�e � l'int�rieur d'une autre classe. Le principal avantage des classes internes vient du fait qu'elles ont acc�s � tous les membres de leur classe conteneur quel que soit le niveau de visibilit�. Ainsi les membres private de la classe conteneur sont visibles par toutes ses classes internes.
Note�: en r�alit� le compilateur g�n�rera implicitement une m�thode d'acc�s synth�tique de visibilit� package-private.
On distingue toutefois quatre grands types de classes internes�:
- les classes internes statiques (static nested classes), qui correspondent � de simples classes d�clar�es � l'int�rieur d'une autre classe�;
- les classes internes (inner classes), qui conservent un lien fort avec une instance de la classe conteneur�;
- les classes locales, d�clar�es dans une m�thode, et qui ne sont valides qu'� l'int�rieur de ce bloc.
- les classes anonymes, d�clar�es en ligne dans le code.
Les deux premiers types (static nested classes et inner classes) �tant d�clar�s au m�me niveau que les membres de la classe, ils peuvent donc b�n�ficier des m�mes possibilit�s de visibilit�: public, protected, package-only (aucun modificateur) ou private. Une classe private ne peut �tre utilis�e que par la classe conteneur tandis qu'une classe protected peut �galement �tre utilis�e par une classe fille ou une classe du m�me package.
Note�: les classes standard ne peuvent pas �tre d�clar�es protected ou private, puisque cela n'aurait aucun sens (une classe ne peut h�riter d'une autre classe que si cette derni�re lui est visible).
Classes internes statiques
Les classes internes statiques (static nested classes) correspondent tout simplement � des classes standard d�clar�es � l'int�rieur d'une autre classe. Elles se distinguent par la pr�sence du mot-cl� static dans leur d�finition.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | public class TopLevelClass { private String privateField; public static class StaticNestedClassComparator implements Comparator<TopLevelClass> { public int compare(TopLevelClass o1, TopLevelClass o2) { // On acc�de directement aux champs priv�s�: return o1.privateField.compareTo(o2.privateField); } } } |
Ces m�thodes peuvent �tre instanci�es directement en les pr�fixant du nom de la classe conteneur (� condition qu'elle soit visible bien entendu)�:
Code Java : | S�lectionner tout |
TopLevelClass.StaticNestedClassComparator instance = new TopLevelClass.StaticNestedClassComparator();
Classes internes
Les classes internes (inner classes) ne sont pas d�clar�es avec le mot-cl� static, et elles gagnent par la m�me occasion un lien �troit avec une instance de la classe conteneur. En effet les classes internes ne peuvent �tre instanci�es qu'� partir d'une instance de la classe parente, avec laquelle elle gardera une relation pendant toute son existence.
Il est ainsi possible d'acc�der � l'instance courante via la notation NomDeLaClasseConteneur.this. Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class TopLevelClass { private String privateField; public class InnerClassRunnable implements Runnable { public void run() { // On peut acc�der directement aux champs priv�s de l'instance li�: System.out.println(TopLevelClass.this.privateField); } } public InnerClassRunnable create() { // On cr�e une instance de l'inner-class qui sera li�e avec l'instance courante (this) return new InnerClassRunnable(); } } |
En contrepartie, il est ainsi obligatoire d'instancier ce type de classe depuis une des m�thodes d'instances de la classe conteneur (par exemple create() ici), ou en utilisant une r�f�rence de l'instance de la classe parente�:
Code Java : | S�lectionner tout |
1 2 | TopLevelClass topLevelInstance = new TopLevelClass(); TopLevelClass.InnerClassRunnable innerInstance = topLevelInstance.new InnerClassRunnable(); |
Mais ce type d'�criture est g�n�ralement d�conseill�.
Note�: pour r�aliser ce lien entre la classe interne et la classe conteneur, le compilateur rajoutera automatiquement un param�tre du type de la classe conteneur � chacun des constructeurs de la classe interne, ainsi qu'un attribut d'instance qui conservera cette valeur. Le code g�n�r� est donc sensiblement identique au code suivant�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | public class InnerClassRunnable implements Runnable { final TopLevelClass topLevelClass; public InnerClassRunnable(TopLevelClass topLevelClass) { this.topLevelClass = topLevelClass; } public void run() { // On peut acc�der directement aux champs priv�s de l'instance li�e�: System.out.println(topLevelClass.privateField); } } |
Note�: les interfaces, annotations ou enums d�clar�es � l�int�rieur d'une classe ne peuvent pas �tre li�es avec une instance de la classe parente, et sont donc implicitement d�clar�es statiques (m�me en l'absence du mot-cl� static).
Classes locales
Les classes locales sont des classes d�clar�es au sein m�me d'une m�thode ou d'un bloc de code. Elles ne peuvent donc �tre utilis�es qu'� l'int�rieur de ce m�me bloc et seront compl�tement inexistantes de l'ext�rieur.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public static void main(final String[] args) throws Exception { // D�claration de la classe au sein d'une m�thode�: class LocalClass { public void sayHello() { System.out.println("Hello World"); } } LocalClass c1 = new LocalClass(); LocalClass c2 = new LocalClass(); c1.sayHello(); c2.sayHello(); } |
Classe anonyme
Les classes anonymes correspondent � une variante des classes locales, dans le sens o� elles sont aussi d�clar�es � l'int�rieur d'un bloc de code. Elles permettent de d�finir une classe � ��usage unique�� en impl�mentant une seule interface ou en h�ritant d'une classe directement, par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public static void main(final String[] args) throws Exception { // Impl�mentation d'une interface�: Runnable task = new Runnable() { public void run() { System.out.println("Hello World"); } }; // H�ritage d'une classe�: Thread thread = new Thread() { public void run() { System.out.println("Hello World"); } }; thread.start(); new Thread(task).start(); } |
Note�: lorsqu'elles sont utilis�es dans une m�thode d'instance, les classes locales et les classes anonymes peuvent �tre li�es � l'instance courante (this) de la m�me mani�re que les classes internes non statiques.
Note�: il faut noter �galement que mis � part pour les classes internes statiques, les classes internes n'acceptent pas d'attribut statique, mis � part s'il s'agit de constantes.
Une interface repr�sente un contrat pass� entre plusieurs classes (polymorphisme). En g�n�ral mais pas toujours, l'interface porte un nom de type adjectif compose autour du suffixe able qui signifie � capable de �, ce qui permet de pr�ciser les aptitudes compl�mentaires d'une classe. Par exemple�:
- Runnable = capable d'�tre ex�cut� �;
- Drawable = capable de s'afficher.
Concept
En g�n�ral, l'interface sp�cifie dans son contrat un ensemble de m�thodes qui devront �tre impl�ment�es par les classes qui s'engagent � respecter le contrat. N�anmoins, ceci n'est pas n�cessaire et certaines interfaces servent uniquement de marqueur, comme l'interface Serialisable qui permet simplement de pr�parer une classe � la s�rialisation.
La notion d'interface permet ainsi de�:
- d�couper, de mani�re � la fois �l�gante et tr�s puissante, l'aptitude (contrat) de l'impl�mentation.
Par exemple l'interface Enumeration permet de parcourir un ensemble d'objets d'un bout � l'autre sans se pr�occuper de l'impl�mentation sous-jacente (un tableau, une table de hachage, une collection, etc.). En effet il suffit de faire une boucle�:Code Java : S�lectionner tout 1
2
3
4while (Enumeration e = ...; e.hasNextElement(); ) { MonObjet o = (MonObjet)e.next(); // Faire qqc avec o }
- de bien s�parer les activit�s, et d'am�liorer ainsi la lecture du code.
En effet, la seule lecture de la d�claration de la classe nous permet de prendre connaissance de l'int�gralit� des activit�s de celle-ci. Par exemple une classe, disons Ensemble qui impl�mente l'interface Sortable nous renseigne d�s sa d�claration sur la notion d'aptitude au tri qui lui a �t� attribu�e.
Utilisation
Les interfaces sont d�finies gr�ce au mot-cl� interface. Une interface peut h�riter d'un nombre infini d'autres interfaces gr�ce au mot-cl� extends. Les m�thodes ainsi que les membres statiques finals d�finis dans une interface sont implicitement d�finis avec l'accesseur public (m�me si ce dernier n'est pas d�clar�).
Les m�thodes d�crites dans une interface ne contiennent pas de corps, seule leur signature est pr�sente. Le mot-cl� abstract ne peut pas �tre utilis� dans une interface.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 | public interface Sortable { void sort(); } |
Ici, notre interface Sortable d�finit la signature d'une m�thode sort() que peut impl�menter une classe fille. Une classe fille doit utiliser le mot-cl� implements pour indiquer qu'elle h�rite d'une interface. Une classe peut h�riter d'un nombre infini d'interfaces.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 | public class MaListe implements Sortable { @Override public void sort() { // Code du tri ici. } } |
Il est bien s�r �galement possible d�impl�menter une interface dans une classe anonyme�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 | Sortable monSortable = new Sortable() { @Override public void sort() { // Code du tri ici. } } |
Si la classe fille n�impl�mente pas les m�thodes d�finies dans l'interface, elle doit �tre d�clar�e abstraite avec le mot-cl� abstract.
Note�: lorsqu'une classe fille impl�mente une m�thode d�finie dans une interface, on peut pr�c�der cette m�thode de l'annotation @Override.
Il est �galement possible de d�finir des membres statiques finals (des constantes statiques) dans une interface�:
Code Java : | S�lectionner tout |
1 2 3 | public interface Constants { public static final double PI2 = 2*Math.PI; } |
Ainsi toutes les classes (et interfaces) qui h�ritent de cette interface Constants h�riteront du membre statique final PI2.
Depuis le JDK8, il est de plus possible de d�finir des m�thodes par d�faut ainsi que des m�thodes statiques dans des interfaces.
Une m�thode par d�faut (defender method) permet de sp�cifier une impl�mentation par d�faut fournie par l'interface. Le but des m�thodes par d�faut est de m�nager les possibilit�s d��volution d'une API en offrant une impl�mentation g�n�rique cens�e toujours fonctionner avec les classes et instances qui impl�mentent le type fourni par l'interface. Une m�thode par d�faut est pr�fix�e par le mot-cl� default.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | public interface Localizable { String getDisplayName(Locale locale); default String getDisplayName() { return getDisplayName(Locale.getDefault()); } } |
Ici, notre interface Localizable a d�fini la m�thode par d�faut getDisplayName() qui se contente d�utiliser la locale par d�faut du syst�me. Ces m�thodes sont toujours surchargeables par les classes filles qui h�ritent de l'interface.
En savoir plus
- Pour en savoir plus sur la notion d'interface, outre les tutoriels Java, il est conseill� de chercher de l'information autour des design patterns.
- Pour mieux comprendre la notion de s�paration des activit�s, il peut �tre int�ressant de lire
les documentations concernant jakarta-avalon .
Java permet de sauvegarder l'�tat d'un objet � un instant donn� dans un flux d'octets. On dirigera g�n�ralement ce flux dans un fichier pour effectuer une sauvegarde. Le principal avantage de la s�rialisation, c'est d'�tre compl�tement int�gr� � l'API Java et donc de ne n�cessiter presque aucun code suppl�mentaire.
Lorsqu'on red�finit une m�thode d'une classe parente, ou lors de l'impl�mentation d'une m�thode d'une classe abstraite ou d'une interface, on doit obligatoirement conserver la signature exacte de la m�thode d'origine�: c'est le contrat que l'on doit respecter. Toutefois, il n'est pas fig� et il est donc possible de modifier certains �l�ments. Pour cela, nous allons prendre la d�claration de la m�thode suivante en exemple�:
Code Java : | S�lectionner tout |
protected Number getValue(int value) throws IOException;
Il est donc possible de modifier les �l�ments suivants�:
- La port�e de la m�thode�: il est en effet possible de changer la port�e de la m�thode, � condition de l'�largir. Ainsi, une m�thode protected peut devenir public alors qu'une m�thode sans modificateur (visibilit� limit�e au package) pourra devenir protected ou public... Cela est possible, car le contrat de la m�thode originale est respect� (on se contente d'�tendre l'acc�s � la m�thode).
Par contre, l'inverse reste interdit�! Il est impossible de passer une m�thode public en protected ou private par exemple.
Ainsi, la m�thode ci-dessous est tout � fait valable�:Code Java : S�lectionner tout public Number getValue(int index) throws IOException;
- Les Exceptions retourn�es�: il est possible de modifier la d�claration des exceptions renvoy�es par la m�thode, tant que l'on respecte celle de la m�thode parente. Il est donc possible de�:
- supprimer l'exception�: en effet, en ne renvoyant pas d'exception, on respecte le contrat original, car le mot-cl� throw signifie ��la m�thode peut renvoyer une exception��, mais ce n'est pas une obligation�;
- sp�cialiser le type de l'exception�: en indiquant par exemple une exception qui h�rite de celle d�finie dans la signature de la m�thode parente.
Ainsi, les deux m�thodes suivantes sont valables (puisque FileNotFoundException et ZipException h�ritent de IOException)�:Code Java : S�lectionner tout protected Number getValue(int value);
Code Java : S�lectionner tout protected Number getValue(int value) throws FileNotFoundException, ZipException;
- La covariance du type de retour�: depuis la version�5.0, Java apporte une nouvelle possibilit�: on peut d�sormais modifier le type de retour de la m�thode. Toutefois, il faut que le nouveau type h�rite du type de retour d'origine afin de ne pas rompre le contrat.
Ainsi, notre m�thode pourrait retourner un Long (puisque Long h�rite de Number)�:Code Java : S�lectionner tout protected Long getValue(int value) throws IOException;
Finalement, on peut obtenir des m�thodes tr�s diff�rentes alors qu'elles red�finissent bien la m�me m�thode�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | public Double getValue(int value); protected Long getValue(int value) throws FileNotFoundException, ZipException; [...] |
Attention�: les changements de signature affecteront bien s�r les classes filles... De plus, il peut devenir difficile de voir qu'une m�thode en red�finit une autre avec tant de modifications. Dans ce cas il est fortement conseill� d'utiliser l'annotation @Override (si possible)...
-
Que signifient les mots-cl�s public, private et protected ?
Tutoriel : La covariance dans le JDK1.5 de Fabrice Sznajderman.
La surcharge (ou encore overload) est le fait de d�clarer plusieurs m�thodes avec le m�me nom, mais avec des param�tres et/ou types de retour diff�rents.
Une m�thode qui surcharge une autre doit obligatoirement�:
- avoir le m�me nom de la m�thode surcharg�e�;
- �tre d�clar�e dans la m�me classe ou dans une classe fille�;
- avoir une signature diff�rente�: param�tres diff�rents en nombre, en types ou en ordre de ceux de la m�thode surcharg�e.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | public class Salutation { public void disBonjour() { System.out.println("Bonjour inconnu�!"); } public void disBonjour(String nom) { System.out.println("Bonjour "+nom+"�!"); } } |
Dans cet exemple, la m�thode disBonjour() est surcharg�e dans le sens o� elle peut �tre appel�e de deux fa�ons diff�rentes�:
Code Java : | S�lectionner tout |
1 2 3 | Salutation salutation = new Salutation(); salutation.disBonjour(); salutation.disBonjour("D�veloppeur"); |
Sortie�:
Code : | S�lectionner tout |
1 2 | Bonjour inconnu�! Bonjour D�veloppeur�! |
Un getter (du verbe anglais to get signifiant obtenir) est le surnom d'une m�thode en acc�s public qui permet de r�cup�rer la valeur d�un membre ou d'une propri�t� private ou protected d'un objet. Le but d'un getter est d'encapsuler l�acc�s � ce membre ou propri�t�, par exemple en cachant le fait que le r�sultat peut provenir d'un appel � une autre m�thode ou m�me d'un sous-objet plut�t que d'un membre ou en s'assurant qu'on retourne un objet en lecture seule ou une copie lorsque la valeur de retour est de type complexe de mani�re � ne pas pouvoir permettre les effets de bord.
Cette m�thode n'a g�n�ralement pas de param�tre d'entr�e et retourne une valeur du m�me type que le membre. Selon la convention, ces m�thodes sont �crites sous la forme get<Nom de la propri�t� avec la premi�re lettre en majuscule>() ou, pour les valeurs bool�ennes, is<Nom de la propri�t� avec la premi�re lettre en majuscule>().
Par exemple�:
- boolean isEnabled() - retourne le statut ��activ頻 du contr�le�;
- int getChildCount() - retourne le nombre d��l�ments enfants�;
- String getPhoneNumber() - retourne le num�ro de t�l�phone�;
- etc.
Un setter (du verbe anglais to set signifiant d�finir) est le surnom d'une m�thode en acc�s public qui permet de sp�cifier la valeur d�un membre ou d'une propri�t� private ou protected d'un objet. Le but d'un setter est d'encapsuler l�acc�s direct � ce membre ou propri�t�, et de permettre de faire, par exemple, des v�rifications sur la validit� des valeurs qui sont affect�es � la propri�t�, de pouvoir positionner des valeurs par d�faut lorsque des valeurs non viables sont pass�es en param�tre ou de pouvoir g�n�rer des exceptions si besoin. Cela permet �galement de lancer une action dans l'objet lui-m�me suite au changement de valeur ou m�me de lancer une notification de modification � tout observateur int�ress� en utilisant l'API d��v�nements.
Cette m�thode n'a pas de valeur de sortie et prend en argument en g�n�ral un seul param�tre du m�me type que le membre. Selon la convention, ces m�thodes sont �crites sous la forme set<Nom de la propri�t� avec la premi�re lettre en majuscule>().
Par exemple�:
- void setEnabled(boolean value) - d�finit si le contr�le est activ�;
- void setChildCount(int value) - d�finit le nombre d��l�ments enfants�;
- void setPhoneNumber(String valeur) - d�finit le num�ro de t�l�phone�;
- etc.
Les Generics (ou types param�tr�s) permettent de s'abstraire du type r�el des objets lors de la conception d'une classe ou d'une m�thode tout en conservant un code s�curis�. En effet, contrairement au polymorphisme tel qu'il �tait utilis� jusque l� dans Java, les Generics permettent de d�finir le type r�el des objets lors de leurs utilisations, et permettent ainsi de s'affranchir des multiples cast peu pratiques et dangereux en cas de mauvaise utilisation. Ainsi, les Generics augmentent la s�curit� en reportant � la compilation des erreurs qui survenaient � l'ex�cution...
Prenons pour exemple l'utilisation des collections de Java, avec une m�thode qui permet de calculer la moyenne d'une List de Float�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | public float moyenne (List listNote) { float moyenne = 0.f; Iterator iterator = listNote.iterator(); while (iterator.hasNext()) { Float note = (Float) iterator.next(); moyenne += note.floatValue(); } return moyenne/listNote.size(); } |
Cette m�thode toute simple peut poser probl�me si on l'utilise mal. En effet, si un seul des �l�ments de la liste pass�e en param�tre n'est pas du type Float, on se retrouve avec une ClassCastException. Si ce type de probl�me est facilement d�celable dans de petits programmes, il en est tout autrement dans de gros projets, et en particulier si la liste en question peut �tre remplie par diff�rents modules...
En permettant de typer des objets, les Generics reportent ces probl�mes � la compilation. Ainsi la m�thode devient�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | public float moyenne (List<Float> listNote) { float moyenne = 0.f; Iterator<Float> iterator = listNote.iterator(); while (iterator.hasNext()) { Float note = iterator.next(); moyenne += note.floatValue(); } return moyenne/listNote.size(); } |
Le cast a disparu, car il a �t� remplac� par le typage de la liste et de son it�rateur gr�ce au <Float> apr�s le nom du type, qui permet d'indiquer que la List et l'Iterator sont tous les deux param�tr�s avec des Float. Ainsi, la m�thode moyenne() ne risque plus de provoquer de ClassCastException puisque tous les �l�ments de la liste sont forc�ment des Float...
Enfin, il est � noter que l'utilisation cumul�e des Generics, de l'auto-boxing et de la boucle for �tendue simplifie grandement la m�thode�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | public float moyenne (List<Float> listNote) { float moyenne = 0.f; for (float note�: listNote) { moyenne += note; } return moyenne/listNote.size(); } |
-
Tutoriel :J2SE 1.5 Tiger, Les G�n�rics par Lionel Roux.
L'auto-boxing g�re la transformation des types primitifs (boolean, byte, char, short, int, long, float, double) vers la classe wrapper correspondante (Boolean, Byte, Character, Short, Integer, Long, Float, Double) et inversement pour l'auto-unboxing.
Tout est transparent, il n'y a donc plus aucune conversion explicite. Ainsi, le code suivant est tout � fait correct :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | Integer integer = 0;// Integer integer = new Integer(0); int j = integer;// int j = integer.intValue(); Map map = new HashMap(); map.put ( 2.1, "Valeur" );// map.put (new Double(2.1), "Valeur"); List list = new ArrayList(); list.add (true);// list.add (new Boolean(true)); [...] |
Attention : si l'objet wrapper est � la valeur null, une exception de type NullPointerException sera g�n�r�e lors de toute tentative d'auto-unboxing. Par exemple :
Code Java : | S�lectionner tout |
1 2 | Integer value = null; int i = value; // G�n�re une NullPointerException. |
-
Tutoriel : J2SE 1.5 Tiger, L'autoboxing des types primitifs par Lionel Roux.
Les annotations permettent de poser des ��marqueurs�� sur divers �l�ments du langage. Elles peuvent ensuite �tre utilis�es par le compilateur ou d'autres outils de gestions des sources afin d'automatiser certaines t�ches, voire directement pendant l'ex�cution de l'application...
Dans le code source, les annotations se distinguent par la pr�sence d'une arobase (@) devant leur nom (� l'instar des tags Javadoc), et elles se d�clarent avec le mot-cl� @interface�:
Code Java : | S�lectionner tout |
1 2 | public @interface SimpleAnnotation { } |
Code Java : | S�lectionner tout |
1 2 3 4 | public @interface AttributAnnotation { String value(); int count(); } |
Elles s'utilisent en pla�ant l'annotation devant l'�l�ment � annoter, avec les valeurs des �ventuels attributs entre parenth�ses, par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @SimpleAnnotation public class MaClasse { @SimpleAnnotation protected String name; @SimpleAnnotation protected int value; @AttributAnnotation(value="info", count=3); public MaClasse () { } @SimpleAnnotation @AttributAnnotation(value="m", count=1); public void method () { } |
Les annotations de base fournies par le langage Java�:
- @Deprecated - qui permet d'indiquer qu'un �l�ment est d�pr�ci� et ne devrait plus �tre utilis�;
- @Override - � placer devant une m�thode permet d'indiquer qu'elle surcharge une m�thode h�rit�e de la classe parent�;
- @SuppressWarnings - permet d'ignorer certains warnings lors de la compilation.
Il existe �galement des m�ta-annotations con�ues exclusivement pour �tre utilis�es sur d'autres annotations�:
- @Documented - permet d'indiquer que l'annotation doit figurer dans la documentation g�n�r�e par javadoc�;
- @Inherited - indique que l'annotation doit �tre h�rit�e par les classes filles�;
- @Retention - sp�cifie de quelle mani�re l'annotation doit �tre conserv�e par le compilateur et la JVM�;
- @Target - permet de limiter les �l�ments du langage qui peuvent prendre cette annotation.
De plus, l'outil javac introduit une option -processor permettant d'analyser le code � la recherche des annotations avant la compilation.
-
Tutoriel : Les annotations de Java 5.0 par AdiGuba.
Une enum repr�sente un type �num�r�, c'est-�-dire un type qui n'accepte qu'un ensemble fini d'�l�ments. Ce type permet donc de cr�er simplement des �num�rations.
Utilisation
Dans sa forme la plus basique, une enum contient simplement la liste des valeurs possibles qu'elle peut prendre. Elle se d�clare comme une classe, mis � part que l'on utilise le mot-cl� enum, par exemple�:
Code Java : | S�lectionner tout |
1 2 3 | public enum Season { spring, summer, automn, winter; } |
Les diff�rentes valeurs de l'enum correspondent � des constantes statiques et publiques et peuvent donc �tre acc�d�es directement comme les champs public static (par exemple avec Season.winter).
Les enums sont type-safe, c'est-�-dire qu'une enum ne peut en aucun cas prendre une autre valeur que celle d�finie dans sa d�claration, c'est pourquoi on ne peut ni construire de nouvelle instance, ni h�riter d'une enum... Ici, les seules valeurs l�gales pour un objet de type Season sont null, Season.spring, Season.summer, Season.automn et Season.winter.
Toutefois, une �num�ration reste une classe Java, elle accepte donc des champs, des m�thodes et des constructeurs. Par exemple, on pourrait compl�ter l'�num�ration avec le nom fran�ais de la saison�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public enum Season { spring("Printemps"), summer("Et�"), automn("Automne"), winter("Hiver"); protected String label; /** Constructeur */ Season(String pLabel) { this.label = pLabel; } public String getLabel() { return this.label; } } |
Il est donc d�sormais possible d'invoquer la m�thode getLabel() sur des objets de type Season�:
Code Java : | S�lectionner tout |
1 2 | Season season = Season.winter; System.out.println(season.getLabel()); |
Les constructeurs des enum sont implicitement priv�s (m�me si l'accesseur private n'est pas sp�cifi�). Ils n'acceptent donc pas de modificateurs d'accessibilit� public ou protected. En effet, ils ne sont utilis�s que pour initialiser les diff�rentes valeurs de l'�num�ration.
Ainsi, le code suivant est incorrect�:
Code Java : | S�lectionner tout |
Season s = new Season("Hiver"); // Code invalide, ne compile pas.
De plus, chaque enum poss�de deux m�thodes statiques implicites permettant d'acc�der aux diff�rentes valeurs�:
- values() - cette m�thode retournera un tableau du type de l'enum avec toutes les valeurs d�finies dans cette derni�re. Par exemple�:
Code Java : S�lectionner tout Season[] seasons = Season.values();
- valueOf(String) - cette m�thode retournera la valeur de l'enum dont le nom est pass� en param�tre. Par exemple�:
Code Java : S�lectionner tout Season season = Season.valueOf("spring") //Retournera Season.spring.
Attention�: une exception de type IllegalArgumentException sera g�n�r�e si la valeur pass�e en param�tre ne correspond pas � une valeur d�finie dans l'enum.
Chaque instance d'une enum poss�de deux m�thodes implicites permettant d'acc�der aux diff�rentes valeurs�:
- ordinal() - cette m�thode retournera l'index auquel cette valeur de l'enum a �t� d�clar�e dans le code. Il s'agit �galement de l'index de cette valeur dans le tableau retourn� par la m�thode statique values(). Par exemple�:
Code Java : S�lectionner tout 1
2
3
4int springIndex = Season.spring.ordinal(); // Vaut 0. int summerIndex = Season.summer.ordinal(); // Vaut 1. int automnIndex = Season.automn.ordinal(); // Vaut 2. int winterIndex = Season.winter.ordinal(); // Vaut 3.
- name() - cette m�thode renvoie la valeur de l'enum sous forme de String. Par exemple�:
Code Java : S�lectionner tout 1
2
3
4String springName = Season.spring.name(); // Vaut "spring". String summerName = Season.summer.name(); // Vaut "summer". String automnName = Season.automn.name(); // Vaut "automn". String winterName = Season.winter.name(); // Vaut "winter".
Enfin, les enums peuvent directement �tre utilis�es dans un switch�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public void method (Season season) { switch (season) { case spring: System.out.println("Les arbres sont en fleurs�!!!"); break; case summer: System.out.println("Il fait chaud�!!!"); break; case automn: System.out.println("Les feuilles tombent..."); break; case winter: System.out.println("Il neige�!!!"); break; } } |
Attention�: une exception de type NullPointerException sera g�n�r�e si season est � la valeur null.
Tutoriel : J2SE 1.5 Tiger, Les types �num�r�s type-safe par Lionel Roux.
Une constante est un attribut static final qui respecte certaines conditions�:
- il doit correspondre � un type primitif (boolean, byte, char, int, long, float ou double) ou au type sp�cial String�;
- sa valeur doit �tre directement affect�e en ligne � la d�claration de l'attribut�;
- sa valeur doit pouvoir �tre �valu�e par le compilateur, c'est-�-dire qu'elle ne doit pas comporter de code dynamique (appel de m�thode ou utilisation de variables), mais de simples op�rations sur des constantes.
� titre d'exemple, les attributs suivants sont des constantes�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 | public static final char CHAR = 'C'; public static final double RAYON = 15.0; public static final double AIRE = Math.PI * RAYON * RAYON; public static final String HELLO = "Hello"; public static final String HELLO_WORLD = HELLO + " World"; |
� l'inverse, les attributs suivants ne sont pas des constantes, mais de simples attributs statiques invariables�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | public static final char CHAR = Character.valueOf('C'); // Appel d'une m�thode. public static final double RANDOM = Math.random(); // Appel d'une m�thode. public static final Object OBJECT = "Object"; // Type incorrect (Object). public static final String HELLO = new String("Hello"); // Utilisation d'un constructeur. public static final String HELLO_WORLD = HELLO + " World"; // HELLO n'est pas une constante. public static final String VALUE; // Pas d'initialisation. static { VALUE = "Value"; } |
Les constantes sont trait�es d'une mani�re particuli�re par le compilateur, et se rapprochent des # define du C/C++. En effet, comme le compilateur peut �valuer leur valeur, il ne g�n�re pas le code d'acc�s � l'attribut, mais le remplacera directement par sa valeur.
Prenons par exemple le code suivant�:
Code Java : | S�lectionner tout |
System.out.println(Constante.HELLO + " World");
Si Constante.HELLO est une constante, le compilateur remplacera directement l'acc�s � l'attribut par sa valeur, ce qui reviendrait � faire ceci�:
Code Java : | S�lectionner tout |
System.out.println("Hello" + " World");
Et, puisque le compilateur se charge d'�valuer les expressions ou sous-expressions ne contenant que des constantes, on obtient directement le code suivant�:
Code Java : | S�lectionner tout |
System.out.println("Hello World");
Il n'y a donc plus aucune concat�nation � l'ex�cution.
Attention toutefois, car si le code source est modifi� pour changer la valeur de la constante, cette modification ne sera pas r�percut�e sur les autres classes si elles n'ont pas �t� recompil�es, puisqu'elles conserveront en dur l'ancienne valeur de la constante. Du fait ce cette sp�cificit�, il est important de ne pas utiliser abusivement les constantes pour des valeurs qui pourraient �tre modifi�es au cours du temps, en particulier dans le cadre du d�veloppement d'une biblioth�que ou d'une API.
Plut�t que d'utiliser des constantes, il est g�n�ralement pr�f�rable d'utiliser des enums ou des objets immuables. Les constantes sont utiles seulement pour des grandeurs fixes et amorphes.
Les membres d'une classe (c'est-�-dire ses attributs, constructeurs ou m�thodes) peuvent �tre marqu�s en tant que ��synthetic�� par le compilateur pour indiquer qu'il s'agit d'un �l�ment qui a �t� introduit par le compilateur et qui n'est donc pas directement pr�sent dans le code source original de la classe.
La plupart du temps les membres synthetic sont g�n�r�s lors de l'utilisation de classes internes, par exemple�:
- une classe interne non static se verra ajouter un attribut r�f�ren�ant l'instance de la classe parente avec laquelle elle est li�e�;
- lorsqu'une classe interne acc�de � une m�thode ou un attribut priv� de la classe parente, le compilateur ajoutera et utilisera en r�alit� une m�thode d'acc�s de visibilit� ��package-only�� dans la classe parente�;
- lorsqu'une classe interne acc�de � un constructeur priv� de la classe parente, le compilateur g�n�rera en fait un autre constructeur de visibilit� ��package-only��.
Bref, tous les membres introduits par le compilateur sans correspondance dans le code source original sont marqu�s comme ��synthetic��, � l'exception toutefois des constructeurs par d�faut (qui sont automatiquement rajout�s lorsqu'une classe ne d�finit aucun constructeur).
Les m�thodes bridges sont des m�thodes ��synthetics�� g�n�r�es par le compilateur sous certaines conditions lors de l'impl�mentation ou la red�finition de m�thodes param�tr�es par les Generics, et que l'on sp�cifie un type particulier.
Prenons l'exemple d'une classe qui impl�mente l'interface Comparator<T> en utilisant le type String�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | public class StringIgnoreCaseComparator implements Comparator<String> { public int compare(String o1, String o2) { return o1.compareToIgnoreCase(o2); } } |
Les param�tres de la m�thode compare() sont bien de type String, or, puisque le type des Generics est perdu � l'ex�cution, la m�thode compare(String, String) ne respecte plus la signature de base de l'interface Comparator qui correspond plut�t � compare(Object, Object) (c'est-�-dire sans les types param�tr�s).
Pour pallier cela, le compilateur g�n�rera automatiquement une m�thode suppl�mentaire correspondant � la signature de base de la m�thode, qui se contentera d'appeler la bonne m�thode apr�s un cast de ses param�tres. Ce qui donnerait dans notre cas�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | public class StringIgnoreCaseComparator implements Comparator<String> { public int compare(String o1, String o2) { return o1.compareToIgnoreCase(o2); } // M�thode bridge cr��e par le compilateur�: public int compare(Object o1, Object o2) { return compare((String)o1, (String)o2); } } |
Afin de pouvoir �tre facilement rep�r�es par l'API de reflection, ces m�thodes sont marqu�es en tant que ��bridge�� par le compilateur.
Dans le langage, on ne peut sp�cifier qu'un type pour un param�tre. Ainsi, si une m�thode doit utiliser des objets qui impl�mentent deux interfaces, on ne peut en utiliser qu'un seul dans la d�finition de la m�thode, ce qui oblige � un cast potentiellement dangereux � l'ex�cution�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | public void method(Serializable data) { Comparable cData = (Comparable) data; // throw ClassCastException // Traitement ici [...] } |
Ce type de code a le d�savantage de provoquer une exception si le type pass� en param�tre n'impl�mente pas la seconde interface.
Avec les Generics, il est possible de reporter ce probl�me � la compilation. En effet les Generics ne se limitent pas seulement � param�trer des classes, ils peuvent �galement s'appliquer aux m�thodes, et ainsi permettent de sp�cifier plusieurs contraintes gr�ce � la covariance�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | public <T extends Serializable & Comparable<T>> void method(T data) { // 'data' impl�mente les interfaces Serializable et Comparable // Traitement ici [...] } |
Dans cet exemple, la m�thode est param�tr�e par un type T qui impl�mente � la fois les interfaces Serializable et Comparable<T>. Ainsi, si la m�thode est utilis�e avec un objet qui n'impl�mente pas ces deux interfaces, le compilateur g�n�rera une erreur � la compilation.
Connues pr�c�demment sous le nom de Single Abstract Method interfaces (SAM Interfaces), les interfaces fonctionnelles introduisent les interfaces qui poss�dent uniquement une seule m�thode d�instance abstraite. Les plus connues sont java.lang.Runnable, java.awt.event.ActionListener, java.util.Comparator. D�s lors qu'une interface poss�de une seule m�thode d�instance abstraite, elle est d�sign�e comme interface fonctionnelle.
Il est aussi possible d'annoter l'interface par @FunctionalInterface. Si une interface est annot�e ainsi et poss�de plus d'une m�thode d�instance abstraite, une erreur de compilation sera produite. C'est un peu le m�me principe qu'avec l'annotation @Override.
L'interface ci-dessous, Runnable poss�de une m�thode et est annot�e @FunctionalInterface�:
Code Java : | S�lectionner tout |
1 2 3 4 | @FunctionalInterface public interface Runnable { void run(); } |
Le nouveau package java.util.function propose d�ailleurs un certain nombre d�interfaces fonctionnelles r�pondant � divers usages.
Les lambdas ont �t� introduits dans la version�8 de Java. D�crite depuis la JSR 335, cette fonctionnalit� permet d'apporter la puissance de la programmation fonctionnelle dans Java. Une expression lambda peut �tre assimil�e � une fonction anonyme, ayant potentiellement acc�s au contexte (variables locales et/ou d'instance) du code appelant. Ces ��fonctions anonymes�� peuvent �tre affect�es dans une interface fonctionnelle. Le code de l�expression lambda servira ainsi d�impl�mentation pour la m�thode abstraite de l�interface. On peut donc les utiliser avec n'importe quel code Java utilisant une telle interface, � condition que la signature de la m�thode corresponde � celle de l�expression lambda.
La syntaxe utilis�e est la suivante�: (param�tres) -> code ou (param�tres) -> { code } quand il y a plus d'une instruction.
Prenons l'exemple du tri des �l�ments d'une collection.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 | Arrays.sort(testStrings, new Comparator<String>() { @Override public int compare(String s1, String s2) { return(s1.length() - s2.length()); } }); |
En utilisant les lambdas, la nouvelle �criture sera�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | // Forme longue�: Arrays.sort(testStrings, (String s1, String s2) -> { return s1.length() � s2.length(); }); // Forme courte (possible uniquement s�il n�y a qu�une instruction)�: Arrays.sort(testStrings, (String s1, String s2) -> s1.length() � s2.length()); // Forme courte avec type implicite des param�tres // (le type est d�duit par le compilateur via l�inf�rence) Arrays.sort(testStrings, (s1, s2) -> s1.length() � s2.length()); |
Les interfaces fonctionnelles servent aux lambdas, facilitant ainsi l'�criture puisqu'elles permettent d'�crire l'impl�mentation de fa�on plus concise.
Nous montrons ci-dessous un exemple d'impl�mentation de l'interface Runnable�:
Code Java : | S�lectionner tout |
Runnable r1 = () -> System.out.println("My Runnable");
Tutoriel sur les nouveaut�s du langage 8 : le projet Lambda par Yohan Beschi.
Une r�f�rence de m�thode est utilis�e pour d�finir une m�thode en tant qu�impl�mentation de la m�thode abstraite d�une interface fonctionnelle. La notation utilise le nom de la classe ou une instance de la classe, suivi de l'op�rateur :: et du nom de la m�thode � r�f�rencer. Le type des param�tres sera d�duit du contexte selon l�interface fonctionnelle vers laquelle on affecte la r�f�rence.
On peut distinguer quatre types de m�thodes r�f�rences�:
- les r�f�rences vers une m�thode statique, qui s�utilisent toujours avec le nom de la classe en pr�fixe. La signature de la r�f�rence correspond alors � la signature de la m�thode.
Code Java : S�lectionner tout 1
2Supplier<Double> random = Math::random; double result = random.get(); // Math.random();
- les r�f�rences vers une m�thode d�instance, li�es � une instance sp�cifique, qui s�utilisent toujours avec l�instance en pr�fixe. Ici �galement, la signature de la r�f�rence correspond � la signature de la m�thode, et tous les appels s�appliqueront sur l�instance d�finie dans la r�f�rence de m�thode�:
Code Java : S�lectionner tout 1
2
3Random r = new Random(); Supplier<Double> random2 = r::nextDouble; double result2 = random2.get(); // r.nextDouble();
- les r�f�rences vers une m�thode d�instance, mais sans lien avec une instance pr�cise. Comme pour les m�thodes statiques, on utilisera comme pr�fixe le nom de la classe. La signature de la r�f�rence correspond alors � la signature de la m�thode, pr�c�d�e par un argument du type de la classe, qui correspondra � l�instance sur laquelle on appellera la m�thode�:
Code Java : S�lectionner tout 1
2
3
4
5
6
7Function<Random,Double> random3 = Random::nextDouble; Random r1 = new Random(); Random r2 = new Random(); Random r3 = new Random(); double result1 = random3.apply(r1); // r1.nextDouble(); double result2 = random3.apply(r2); // r2.nextDouble(); double result3 = random3.apply(r3); // r2.nextDouble();
- enfin, il est possible de r�f�rencer un constructeur en utilisant le mot-cl� new comme nom de m�thode. Tr�s pratique pour cr�er une fabrique�:
Code Java : S�lectionner tout 1
2Function<String, Thread> factory = Thread::new; Thread t = factory.apply("name"); // new Thread("name");
Les r�f�rences de m�thodes sont un substitut aux expressions lambdas, lorsqu�il n�y a qu�une seule et unique m�thode � ex�cuter, pour une syntaxe encore plus claire�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | Random r = new Random(); Supplier<Double> random = Math::random; Supplier<Double> random2 = r::nextDouble; Function<Random,Double> random3 = Random::nextDouble; Function<String, Thread> factory = Thread::new; Supplier<Double> random = () -> Math.random(); Supplier<Double> random2 = () -> r->nextDouble(); Function<Random,Double> random3 = (Random random) -> random.nextDouble(); Function<String, Thread> factory = (String name) -> new Thread(name); |
Cela peut �galement �tre un substitut int�ressant � l�API de reflection, puisque cela permet un code s�curis�.
Une m�thode par d�faut (Defender Methods) permet de proposer une impl�mentation dite ��par d�faut�� aux m�thodes d�clar�es dans les interfaces. Par cons�quent, depuis Java 8, une interface Java contient du code. L'avantage est de pouvoir faire �voluer les interfaces sans avoir � tout casser.
Dans l'exemple ci-dessous, une interface Person d�clare deux m�thodes. La m�thode sayHello() est dite par d�faut via le mot-cl� default. Toute impl�mentation de Person imposera que la m�thode sayGoodBye() soit impl�ment�e. Pour sayHello(), l'impl�mentation ne sera pas obligatoire, m�me si elle reste bien s�r possible.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 | interface Person { void sayGoodBye(); default void sayHello() { System.out.println("Hello there!"); } } |
Les m�thodes par d�faut permettent ainsi de faire �voluer l�API des interfaces sans provoquer de grosses incompatibilit�s dues � l�absence d�impl�mentation dans les classes qui les impl�mentent. L�API de base en profite grandement en enrichissant certaines de ses interfaces (en particulier dans l�API de Collections dont les interfaces s�enrichissent de plusieurs m�thodes).
Tutoriel sur Java 8 : du neuf dans les interfaces par Olivier Croisier.
Un objet immuable est un objet dont on ne peut plus modifier l'�tat une fois l'instance cr��e.
La classe String est l'exemple le plus utilis� d'objet immuable�: il n'est pas possible de modifier une chaine de caract�res. Toutes les m�thodes de la classe ou m�me l'op�rateur + qui lui sont appliqu�s retournent en fait une nouvelle chaine distincte de la premi�re.
Prenons, par exemple, le code suivant�:
Code Java : | S�lectionner tout |
1 2 3 | String maChaine = "Test par Moi"; maChaine.toUpperCase(); System.out.println(maChaine); |
Dans ce cas, la deuxi�me instruction ne modifie pas le contenu de la variable maChaine mais cr�e un nouvel objet en retour. C'est bien la valeur "Test par Moi" qui sera affich�e au lieu de "TEST PAR MOI".
Si vous souhaitez que maChaine prenne pour valeur le r�sultat de la deuxi�me instruction, il faut r�affecter la nouvelle valeur dans la variable en proc�dant comme suit�:
Code Java : | S�lectionner tout |
1 2 3 | String maChaine = "Test par Moi"; maChaine = maChaine.toUpperCase(); System.out.println(maChaine); |
� noter que les classes de type wrapper du package java.lang sont immuables�: Boolean, Byte, Character, Short, Integer, Long, Float et Double.
En informatique, et en repr�sentation binaire, on groupe les bits par paquet de 8 (un octet ou byte). On note traditionnellement les bits de poids fort (ceux avec la plus grande puissance de 2) sur la gauche et les bits de poids faible (ceux avec la plus faible puissance de 2) sur la droite.
Par exemple�:
Code Console : | S�lectionner tout |
2726252423222120
Ce qui permet d��crire�:
Code Console : | S�lectionner tout |
00000011 ↔ 21 + 20 ↔ 2 + 1 ↔ 3
Les choses se compliquent lorsqu'on manipule des donn�es qui font plusieurs octets, par exemple des mots, qui font 4 octets, soit 32 bits. Ces mots sont donc constitu�s de bits qui vont du bit0 au bit31, eux-m�mes group�s en 4 octets�: octet31-24, octet23-16, octet15-8 et octet7-0. Chaque fabricant de microprocesseurs a eu sa petite id�e sur la mani�re de stocker une telle structure en m�moire tout en essayant d'optimiser la chose pour son architecture � lui et pas celle des autres. Grosso modo deux principaux modes de stockage ont fini par �merger entra�nant de nombreuses disputes et batailles rang�es pour savoir laquelle des deux �tait la meilleure�; on parle

- sur les architectures IBM, Cray, Sun, etc., on a tendance � agencer les bits de la mani�re suivante�:
Code Console : S�lectionner tout 231230229228227226225224 223222221220219218217216 2152142132122112102928 2726252423222120
Soit�:Code : S�lectionner tout Octet31-24 Octet23-16 Octet15-8 Octet7-0
- tandis que, sur les architectures Intel, on a tendance � agencer les bits de la mani�re suivante�:
Code Console : S�lectionner tout 2726252423222120 2152142132122112102928 223222221220219218217216 231230229228227226225224
Soit�:Code : S�lectionner tout Octet7-0 Octet15-8 Octet23-16 Octet31-24
En avril 1980, alors qu'Internet est en pleins balbutiements et qu'on commence donc � interconnecter les machines et donc les architectures, il faut d�finir des formats communs sur la mani�re de faire transiter des donn�es. Alors que les d�bats font rage,




Depuis, le terme est rest�:
- Big-Endian (gros-boutiste ou grand-boutien) - les octets de poids fort sont � gauche�: architecture IBM, CRAY, Sun, etc.�;
- Little-Endian (petit-boutiste ou petit-boutien) - les octets de poids faible sont � gauche�: architecture Intel.
Certains langages ne g�rent pas vraiment le boutisme et se contentent d'appliquer directement le boutisme support� par la plateforme sous-jacente. Ainsi, avec ces langages, si on n'y prend pas garde, le m�me code qui �crit dans un fichier ou sur le r�seau peut donner des r�sultats compl�tement diff�rents quand il est compil� et ex�cut� sur machines d'architecture diff�rente. Et c'est tr�s important d'y faire attention�; prenons, par exemple, la valeur 3�:
Code Console : | S�lectionner tout |
1 2 | 3 sur une machine gros-boutiste ↔ 00000000 00000000 00000000 00000011 ↔ 50331648 sur une machine petit-boutiste. 3 sur une machine petit-boutiste ↔ 00000011 00000000 00000000 00000000 ↔ 50331648 sur une machine gros-boutiste. |
Si on ne g�re pas correctement le boutisme, on ne lit pas du tout la bonne valeur, ce qui est tr�s g�nant quand il faut allouer des structures, tailles de messages, etc.
Ce n'est pas le cas de Java�: Java est Big-Endian�! Et il l'est de tout temps, et ce, quelle que soit sa plateforme d�ex�cution�; que ce soit pour la repr�sentation binaire des nombres entiers, l��criture et la lecture des fichiers ou encore les acc�s r�seau. Donc, si vous �tes amen� � produire ou lire des fichiers binaires ou des trames r�seau dans lesquels les donn�es doivent �tre sous une forme petit-boutiste, vous devrez faire l'effort d'inverser les octets de vos mots et autres paquets d'octets. Certaines biblioth�ques r�centes, telles que la biblioth�que NIO.2 introduite dans le JDK7, peuvent cependant disposer de classes et m�thodes utilitaires qui permettent d�all�ger votre charge de travail en effectuant cette inversion automatiquement.
Un singleton est un objet qui ne peut �tre instanci� qu'une seule et unique fois dans le programme.
Pour transformer une classe en singleton, il faut passer les constructeurs en acc�s private et ajouter au code une instance et un accesseur statiques�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Singleton { private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } private Singleton() { //constructeur } //reste de la classe } |
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Singleton { private static Singleton instance = null; public static Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; } private Singleton() { //constructeur } //reste de la classe } |
Code java : | S�lectionner tout |
Singleton s = Singleton.getInstance();
Il existe encore une derni�re variante consistant � utiliser une classe interne statique comme conteneur du singleton�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | public class Something { private Something() { } private static class LazyHolder { private static final Something something = new Something(); } public static Something getInstance(){ return LazyHolder.something; } } |
La m�thode equals() permet d'indiquer qu'un objet est �gal � un autre. L'impl�mentation par d�faut h�rit� de Object se contente de renvoyer true lorsqu'il s'agit du m�me objet en m�moire et ne v�rifie pas les valeurs des attributs de la classe (donc x.equals(y) �quivaut � x==y).
D�s lors que l'on a besoin de tester l'�galit� des instances d'une classe, il faut que cette derni�re red�finisse la m�thode equals(). C'est �galement une condition pour le bon fonctionnement de certaines m�thodes des Collections de Java.
La m�thode equals() doit donc renvoyer true lorsque deux objets sont identiques, et false dans le cas inverse. Enfin il faut noter que cette m�thode ne devrait pas renvoyer d'exception, m�me si son param�tre vaut null.
En g�n�ral la m�thode equals() se d�compose en trois �tapes�:
- v�rification de l'�galit� des r�f�rences�: il est inutile de comparer les valeurs si les r�f�rences sont identiques�;
- v�rification du type du param�tre�: on ne peut pas comparer n'importe quel type�;
- v�rification des valeurs des attributs utiles des deux objets (c'est-�-dire des attributs repr�sentatifs de la valeur de l'objet).
Ainsi, cela pourrait donner�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class TestClass { private int attribut1; private String attribut2; private boolean visible; // Attribut non repr�sentatif et donc ignor� @Override public boolean equals(Object obj) { // V�rification de l'�galit� des r�f�rences if (obj==this) { return true; } // V�rification du type du param�tre if (obj instanceof TestClass) { // V�rification des valeurs des attributs TestClass other = (TestClass) obj; // Pour les attributs de type primitif // on compare directement les valeurs�: if (this.attribut1�!= other.attribut1) { return false; // les attributs sont diff�rents } // Pour les attributs de type objet // on compare dans un premier temps les r�f�rences if (this.attribut2�!= other.attribut2) { // Si les r�f�rences ne sont pas identiques // on doit en plus utiliser equals() if (this.attribut2 == null ||�!this.attribut2.equals(other.attribut2)) { return false; // les attributs sont diff�rents } } // Si on arrive ici c'est que tous les attributs sont �gaux�: return true; } return false; } } |
Il faut prendre en compte les r�gles suivantes lors de la red�finition de la m�thode equals()�:
- R�flection: x.equals(x) devrait toujours retourner true�;
- Sym�trie: Si x.equals(y) retourne true,alors y.equals(x) retournera true.�;
- Transitivit�: Si x.equals(y) retourne trueet y.equals(z) retourne true,alors x.equals(z) retourne true.�;
- Consistance: Pour deux r�f�rences x ety, tous les appels � la m�thode x.equals(y)devront toujours donner le m�me r�sultat.
Toutefois ces r�gles peuvent �tre difficilement r�alisables en cas d'h�ritage lorsque de nouveaux attributs sont pris en compte.
Enfin, la biblioth�que Jakarta Common Lang propose une classe EqualsBuilder qui facilite et simplifie l'�criture des m�thodes equals() en se chargeant de la comparaison des attributs, ce qui pourrait donner dans ce cas�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public boolean equals(Object obj) { // V�rification de l'�galit� des r�f�rences if (obj==this) { return true; } // V�rification du type du param�tre if (obj instanceof TestClass) { // V�rification des valeurs des attributs TestClass other = (TestClass) obj; return new EqualsBuilder() .append(this.attribut1, other.attribut1) .append(this.attribut2, other.attribut2) .isEquals(); } return false; } |
Enfin, il faut noter qu'il est conseill� de red�finir �galement la m�thode hashCode() afin de respecter le contrat de cette derni�re (qui est fortement li� � equals()).
La m�thode hashCode() a pour objectif de fournir un code de hashage, afin d'optimiser le traitement des collections de type Map, qui se basent sur ce hashCode pour classer les donn�es. Il est ainsi n�cessaire de red�finir la m�thode hashCode() d�s que l'on souhaite utiliser un objet en tant que cl� d'une Map.
Mais plus g�n�ralement, il est souhaitable de red�finir la m�thode hashCode() lorsque l'on red�finit la m�thode equals(), afin de conserver une certaine coh�rence.
En effet, ces deux m�thodes sont tr�s li�es, puisque les hashCode de deux objets �gaux doivent �tre �gaux, ainsi l'on doit v�rifier la condition suivante�:
Si x.equals(y), alors x.hashCode() == y.hashCode()
Par contre l'inverse n'est pas forc�ment vrai. Ainsi deux objets diff�rents peuvent avoir le m�me hashCode(). Toutefois ceci est � �viter dans la mesure du possible, car cela peut d�t�riorer les performances des Map.
Mais le calcul du hashCode() doit rester raisonnable et peu complexe, afin d'�viter des temps de calcul trop importants.
La solution la plus courante est de calculer un hashCode() selon la valeur des attributs utilis�s dans la m�thode equals() afin de conserver la coh�rence entre les deux m�thodes.
Pour le calcul du hashCode(), on peut raisonnablement suivre la r�gle suivante.
- On choisit deux nombres impairs diff�rents de z�ro. Un de ces nombres servira comme valeur de d�part pour le calcul du hashCode. Le second servira de ��multiplieur�� � chaque ��ajout�� du hashCode d'un attribut. Il est pr�f�rable d'utiliser des nombres premiers par s�curit�.
En effet, si � chaque cl� x , correspond h(x) l'endroit o� se trouve x dans la table de hachage. L'expression de la fonction de Hachage est�:
Code : | S�lectionner tout |
h(x)=[x(1)*B^(l-1) + x(2)*B^(l-2)....+x(l)] mod N
Code : | S�lectionner tout |
h(x)=x(l) mod N
Une seule valeur a donc �t� rang�e dans la table, voil� pourquoi il est tr�s important de limiter au maximum les risques de diviseurs communs, car certaines valeurs dispara�traient alors des tables.
N.B. Le choix de B comme d'une puissance de 2 au lieu d'un nombre premier peut s'av�rer judicieux pour des raisons de vitesse d'ex�cution. En effet une multiplication par 2 est un simple d�calage d'un bit � gauche pour l'ordinateur. Malgr� tout, cela augmente les risques de diviseurs communs et donc de disparition de donn�es.
- Calcul du hashCode de chaque attribut utile (ceux utilis�s dans la m�thode equals()), ce qui revient � faire (soit 'a' l'attribut)�:
- Pour un boolean, renvoyer 0 ou 1
Code java : S�lectionner tout (a�? 0�: 1)
- Pour type entier (byte, char, short ou int) il suffit de prendre la valeur enti�re (avec un cast �ventuel)�:
Code java : S�lectionner tout (int)a;
- Pour un type long, le convertir en int en d�pla�ant les bits�:
Code java : S�lectionner tout (int) (a^(a>>>32))
- Pour le type float, on le convertit en int avec la m�thode Float.floatToIntBits(a).
- Pour le type double, on le convertit en long avec la m�thode Double.doubleToLongBits(a), puis on effectue le m�me traitement que pour les long.
- Pour les objets, on se contentera d'utiliser la m�thode hashCode(), ou d'utiliser z�ro si la r�f�rence est null�:
Code java : S�lectionner tout (object==null�? 0, object.hashCode())
- Pour un tableau, on traitera tous les �l�ments de ce dernier en respectant les r�gles ci-dessus.
Et enfin, on ajoute chacun des hashCodes calcul�s au r�sultat, apr�s l'avoir multipli� par le nombre ��multiplieur��.
Ce qui pourrait donner (pour la classe en exemple dans la question pr�c�dente)�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public int hashCode() { // On choisit les deux nombres impairs int result = 7; final int multiplier = 17; // Pour chaque attribut, on calcule le hashcode // que l'on ajoute au r�sultat apr�s l'avoir multipli� // par le nombre "multiplieur"�: result = multiplier*result + attribut1; result = multiplier*result + (attribut2==null�? 0�: attribut2.hashCode()); // On retourne le r�sultat�: return result; } |
Enfin, la biblioth�que Jakarta Common Lang propose �galement une classe HashCodeBuilder qui facilite et simplifie l'�criture des m�thodes hashCode() en se chargeant du calcul des hashCode des attributs selon leur type, ce qui pourrait donner dans ce cas�:
Code java : | S�lectionner tout |
1 2 3 4 5 6 | public int hashCode() { return new HashCodeBuilder(17, 37) .append(this.attribut1) .append(this.attribut2) .toHashCode(); } |
Un POJO ou Plain Old Java Object (un bon vieil objet Java) est un objet Java tout simple qui ne suit (presque) aucun concept de design ou framework particulier dans sa conception. Ce terme a �t� invent� par Martin Fowler, Rebecca Parsons et Josh MacKenzie en septembre 2000 alors qu'ils s��tonnaient de l'opposition apparente � l'utilisation d'objets � la conception tr�s simple dans le code et en concluaient, avec humour, que cela venait probablement du fait que de tels objets ne disposaient pas d'une d�signation ��cool��. Ils sont � mettre en opposition � des objets ��lourds�� et complexes tels que les Entrerprise Java Beans par exemple.
Donc, pour r�sumer, un POJO�:
- n�h�rite pas d'objet pr�sp�cifi�;
- n�impl�mente pas des interfaces pr�sp�cifi�es�;
- n'utilise pas d'annotation pr�sp�cifi�e.
Cependant, on consid�re g�n�ralement qu'un bean simple (avec des getters et des setters) est un POJO, m�me s'il h�rite de l'interface java.lang.Serializable. De fait, � cause de l�encapsulation des donn�es et des conventions de nommage des m�thodes, de nombreux POJO sont aussi des beans sans le savoir.
De plus, on consid�re g�n�ralement que si un objet �tait un POJO avant qu'on lui ajoute des annotations, il le reste apr�s coup.
Pour copier un objet, deux mani�res de faire s'offrent � vous.
Copie manuelle
Vous pouvez effectuer une copie manuelle de l'objet dans une nouvelle instance, par exemple en le passant dans un constructeur sp�cialis� (aussi appel� constructeur de copie) de cette classe ou via une m�thode de fabrique charg�e de dupliquer l'objet. Par exemple�;
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class Article { private int prix; private int quantite; private String nom; /** * Constructeur normal. */ public Article(String nom, int prix, int quantite) { this.prix = prix; this.quantite = quantite; this.nom = nom; } /** * Constructeur de copie. */ public Article(Article source) { Objects.requiresNonNull(source); this.prix = source.prix; this.quantite = source.quantite; this.nom = source.nom; } } |
Ce qui permet de faire�:
Code Java : | S�lectionner tout |
1 2 | Article source = [...] Article copie = new Article(source); |
Cette fa�on de faire � un gros d�savantage�: elle s'adapte mal � l�h�ritage et au fait de pouvoir �tendre les capacit�s des classes. Par exemple, ici si nous cr�ons une classe ArticleDeMarque qui h�rite de Article et qui contient un membre marque suppl�mentaire, alors notre constructeur de copie est totalement incapable de copier ce nouveau membre.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | public class ArticleDeMarque extends Article { private String marque; public ArticleDeMarque(String nom, int prix, int quantite, String marque) { super(nom, prix, quantite); this.marque = marque; } } |
Il faudrait cr�er puis invoquer un nouveau constructeur de copie sp�cialis� qui serait d�fini dans ArticleDeMarque ce qui suppose d��crire du code qui teste le type de l'objet � copier.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | Article source = [...] Article copie = null; if (source instanceof ArticleDeMarque) { copie = new ArticleDeMarque((ArticleDeMarque) source); } else { copie = new Article(source); } |
Bref, ce n'est pas vraiment viable sur le long terme. Cette fa�on de faire est surtout � r�server pour les classes d�clar�es avec le modificateur final, celles qu'on ne peut plus �tendre ou, au contraire, des classes faisant partie d'une API complexe d�finissant un socle de m�thodes communes pour acc�der au contenu des instances (ex.�: les collections).
Clonage
Java offre un m�canisme permettant de cloner les objets, c'est-�-dire d'invoquer la m�thode clone() d�finie sur une instance de l'objet. C'est cette m�thode qui se chargera de fournir une copie de l'instance en r�sultat.
La m�thode clone() est d�finie directement dans la classe java.lang.Object et est donc accessible depuis n'importe quel objet en Java. Cependant, elle est d�finie en visibilit� protected. De plus, si vous tentez de l'invoquer directement, votre code provoquera une exception de type java.lang.CloneNotSupportedException.
Lorsque vous cr�ez une nouvelle classe que vous d�sirez pouvoir cloner, vous devez lui faire �tendre l'interface de marquage java.lang.Cloneable�; cela permet d��viter la g�n�ration de l'exception. Ensuite vous pouvez surcharger la m�thode clone() pour lui donner une visibilit� public ce qui permettra de l'invoquer depuis du code externe. Enfin, la covariance permet �galement de sp�cifier un type de retour appropri� pour la m�thode. Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Article implements Cloneable { private int prix; private int quantite; private String nom; public Article(String nom, int prix, int quantite) { this.prix = prix; this.quantite = quantite; this.nom = nom; } @Override public Article clone() throws CloneNotSupportedException { // Cet appel cr�era l'instance de la copie, // et recopiera les valeurs de tous les membres dans cette nouvelle instance. Article copie = (Article) super.clone(); return copie; } } |
Ce qui nous permet de faire�:
Code Java : | S�lectionner tout |
1 2 | Article source = [...]; Article copie = source.clone(); |
Ce qui permet de faire des copies sans se soucier du type concret des objets�:
Code Java : | S�lectionner tout |
1 2 | Article source = new ArticleDeMarque([...]); Article copie = source.clone(); |
En effet, le clonage du membre marque de notre classe ArticleDeMarque est assur� par la d�finition de clone() que nous avons �crite dans sa classe m�re Article.
Par d�faut, le clonage se contente de recopier les valeurs des membres des types primitifs et des r�f�rences. Ainsi si notre classe contient une r�f�rence vers un objet complexe, c'est la r�f�rence de l'objet qui est copi�e et non pas l'objet lui-m�me et donc le clone obtenu d�tiendra une r�f�rence vers la m�me instance de cet objet. Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 | public class Article implements Cloneable { [...] private List<Integer> encheres = new LinkedList(); } |
D�sormais notre article contient une liste des ench�res effectu�es. Si nous faisons�:
Code Java : | S�lectionner tout |
1 2 | Article source = [...] article copie = source.clone(); |
Nos deux objets source et copie se partagent la m�me liste encheres ce qui fait que toute modification dans l'un des deux sera �galement r�percut�e dans l'autre.
Pour corriger ce probl�me, nous allons reprendre la d�finition de la m�thode clone() et nous allons nous assurer que nous cr�ons bien une copie de la liste�; c'est ce qu'on appelle le deep cloning ou le clonage en profondeur�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 | @Override public Article clone() throws CloneNotSupportedException { Article copie = (Article) super.clone(); // On cr�e une nouvelle liste qui est la copie de la liste source. // Noter que LinkedList utilise un constructeur de copie. copie.encheres = new LinkedList(this.encheres); return copie; } |
Avertissements�: ici, notre liste contient de simples entiers et nous pouvons nous contenter d'un seul niveau de profondeur de clonage. Si notre liste avait contenu des objets complexes mutables, il aurait �galement fallu copier/cloner chacun des objets de la liste pour �viter les effets de bord.
De plus, notre membre ench�res ne peut pas �tre d�clar� final, car alors la m�thode clone() ne pourrait pas modifier la valeur du membre dans la copie.
Proposer une nouvelle r�ponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �aLes sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.