FAQ Langage JavaConsultez toutes les FAQ

Nombre d'auteurs : 41, nombre de questions : 296, dernière mise à jour : 8 mars 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.


SommaireBases du langageBeans (6)
précédent sommaire suivant
 

Java Beans est le nom d'une architecture logicielle qui permet de définir des composants logiciels réutilisables nommés beans (haricots). Ils ne doivent pas être confondus avec les Entreprise Java Beans qui permettent de définir des composants logiciels, côté serveur, avec Java EE.

Le but initial de Sun Microsystems lors de la définition des spécifications des Java Beans en 1997 était de créer des composants logiciels qui soient susceptibles d’être manipulés dans des éditeurs et des logiciels tiers de conception graphiques de manière à concurrencer ce qu'il était déjà possible de faire, à l’époque, via les composants COM/DCOM/ActiveX disponibles dans Visual Studio et Office de Microsoft. Cela n'implique pas forcément que les beans soient des composants graphiques (ex. : bouton, barre de défilement, etc.) mais cela implique que le bean peut avoir une représentation dans un logiciel tiers et que cette représentation lui permet d'être manipulé via des éditeurs graphiques (ex. : dans un métalogiciel de conception de base de données, un bean représentant un module logiciel permet d’établir une connexion à une base de données peut apparaître sous la forme d'objet éditable graphiquement).

Bien que le but initial de pouvoir s'interfacer et interagir de manière transparente avec des logiciels natifs utilisant des architectures complètement différentes n'ait jamais été pleinement atteint, le concept de bean est toujours fortement ancré dans l'API et les outils Java actuels. D'ailleurs presque tous les composants et contrôles graphiques AWT, Swing et JavaFX sont des beans et beaucoup d'IDE (NetBeans, Eclipse, etc.), d'outils de conception d'UI, de conception graphique, etc. Java fonctionne aujourd'hui, car reposant sur les concepts exposés par l'architecture Java Beans. Le JDK offre un support des beans via l'API disponible dans le package java.beans.

Un bean en lui-même peut être une collection de plusieurs sous-objets dont les fonctionnalités sont accessibles via un objet public unique qui sert de façade publique. Pour pouvoir être qualifié de bean, un objet doit :

  • être sérialisable pour pouvoir sauvegarder et restaurer son état ;
  • disposer d'un constructeur sans argument ou par défaut qui soit publiquement accessible ;
  • encapsuler l’accès à ses membres via des méthodes getters et setters (ce qui forme ce qu'on appelle une propriété). Ce qui les rend manipulables par des éditeurs externes ; les conventions de nommage adoptées pour ces méthodes permettent en effet de retrouver aisément les propriétés du bean par introspection.


Avertissement : l'architecture Java Beans n'est pas exempte de défauts et fait parfois apparaître son grand âge : par exemple, elle se repose lourdement sur l’introspection et ignore presque complètement les annotations (qui n'existaient pas lorsqu'elle a été rédigée). Plusieurs modifications et ajouts apportés dans les JDK 1.4, 6, etc. dans l'API de gestion des beans fournie avec le JDK n'ont jamais été reportés dans les spécifications.

Parmi les défauts les plus apparents, on peut signaler :

  • la norme est principalement définie via des conventions de nommage à suivre plutôt que des interfaces ou classes à implémenter, ce qui peut rendre la validation d'un bean complexe ;
  • le fait d'avoir uniquement un constructeur sans argument peut faire qu'un objet soit dans un état incohérent à sa création si on ne l'initialise pas tout de suite après avec des appels à ses setters ;
  • le support de la sérialisation des propriétés immuables est pratiquement inexistant avant le JDK  6 et, même après ne reste que partiel au mieux ;
  • la norme permet au bean de fournir en option de lui-même son propre éditeur graphique réutilisable dans un logiciel tiers pour permettre la manipulation de ses propres propriétés, mais, compte tenu de l'âge des spécifications, cette partie de l'API ne supporte que les éditeurs compatibles avec le toolkit AWT.

Mis à jour le 15 octobre 2015 bouye

La classe suivante est un bean : elle est sérialisable, dispose d'un constructeur sans argument accessible publiquement et encapsule ses propriétés grâce à des accès via des getters et des setters.

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 Person implements Serializable { 
  
    private final long serialVersionUID = 0L; 
  
    private int id; 
    private String name; 
  
    public Person() { 
        // Initialisations. 
        [...] 
    } 
  
    public int getId() { 
        return id; 
    } 
  
    public String getName() { 
        return name; 
    } 
  
    public void setName(String value) { 
        name = value; 
    } 
}

Ici, id est une propriété immuable ou en lecture seule (on a seulement un getter) tandis que name est une propriété en lecture-écriture (on a un getter et un setter). Il est aussi possible de créer des propriétés en écriture seule (on a alors uniquement un setter).

Cependant, dans les faits et en l’état actuel des choses, beaucoup d’éditeurs graphiques et de logiciels de conception peuvent fonctionner avec des objets qui ne sont pas sérialisables d'autant plus que le JDK 1.4 introduit la possibilité de sérialiser les beans via XML de manière indépendante de la sérialisation native. Ceci fait que du moment qu'ils respectent les conventions de nommage des setters et getters, beaucoup de POJO sont de facto des beans et il est assez courant que la norme Java Beans ne soit pas intégralement implémentée dans les classes publiées par des parties tierces.

Ainsi la classe POJO suivante, bien que non sérialisable, peut aussi être considérée comme étant un bean :

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
public class Person { 
  
    private int id; 
    private String name; 
  
    public Person() { 
        // Initialisations. 
        [...] 
    } 
  
    public int getId() { 
        return id; 
    } 
  
    public String getName() { 
        return name; 
    } 
  
    public void setName(String value) { 
        name = value; 
    } 
}

De plus, la limitation d'avoir un constructeur sans argument est levée à partir du JKD 6.

Mis à jour le 15 octobre 2015 bouye

À partir du JDK 6, il est possible de créer des beans qui ont des constructeurs prenant des arguments. L'annotation java.beans.ConstructorProperties (@ConstructorProperties) permet en effet de faire correspondre chaque paramètre du constructeur du bean avec une de ses propriétés nommées.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person { 
  
    private int id; 
    private String name; 
  
    @ConstructorProperties({"id", "name"}) 
    public Person(int param1, String param2) { 
        this.id = param1; 
        this.name = param2; 
    } 
  
   [...] 
}

Ici, le paramètre param1 est associé à la propriété id ; tandis que le paramètre param2 est associé à la propriété name.

Cela implique plusieurs changements notables :
  • la désérialisation peut désormais créer une instance de cette classe alors qu'elle ne le pouvait pas quand ce constructeur n’était pas annoté ;
  • le fichier XML qui stocke la forme sérialisée du bean a une présentation différente du contenu ;
  • la propriété en lecture seule id, qui n’était pas sauvegardée précédemment, l'est désormais ;
  • il est même possible de marquer le membre id avec le modificateur final sans que cela cause de soucis lors de la désérialisation.

Mis à jour le 15 octobre 2015 bouye

Dans un bean, les propriétés dont les valeurs sont stockées sous forme de tableau sont de type indexed property ou propriété indexée. La norme Java Bean permet de définir des getters et des setters qui peuvent directement accéder à un indice donné du tableau. Par exemple, la propriété suivante retourne les notes scolaires sous forme de tableau :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
private int testGrades; 
  
public int[] getTestGrades() { 
    return testGrades; 
} 
  
public void setTestGrades(int[] value) { 
    testGrades = value; 
}

Cependant, il est possible de définir getters et des setters indexés :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
public int getTestGrades(int index) { 
    return testGrades[index]; 
} 
  
public void setTestGrades(int index, int value) { 
    testGrades[index] = value; 
}

Mis à jour le 15 octobre 2015 bouye

Il est possible de rendre les propriétés d'un bean observables ; c'est-à-dire que le bean émettra un évènement de type java.beans.PropertyChangeEvent lorsqu'une de ses propriétés change de valeur. Cet évènement peut être récupéré par les écouteurs de type java.beans.PropertyChangeListener qui se sont enregistrés auprès du bean. Ces propriétés sont de type bound property ou propriété liée.

Pour ce faire, nous allons tout d'abord modifier notre bean comme suit pour permettre l'enregistrement et le désenregistrement d’écouteurs :

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
public class Person { 
  
    [...] 
  
    private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); 
  
    public void addPropertyChangeListener(PropertyChangeListener listener) { 
        propertyChangeSupport.addPropertyChangeListener(listener); 
    } 
  
    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { 
        propertyChangeSupport.addPropertyChangeListener(propertyName, listener); 
    } 
  
    public void removePropertyChangeListener(PropertyChangeListener listener) { 
        propertyChangeSupport.removePropertyChangeListener(listener); 
    } 
  
    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { 
        propertyChangeSupport.removePropertyChangeListener(propertyName, listener); 
    } 
}

Nous utilisons une instance de la classe java.beans.PropertyChangeSupport pour stocker les écouteurs et nous mettons à disposons deux variantes de chaque méthode :

  • une variante qui permet d'enregistrer ou de désenregistrer un listener de manière globale ;
  • une variante qui permet d'enregistrer ou de désenregistrer un listener de sur une propriété nommée ciblée.


Nous pouvons maintenant modifier notre setter comme suit :

Code Java : Sélectionner tout
1
2
3
4
5
6
public void setName(String value) { 
    String oldName = name; 
    name = value; 
    // Lancement de la notification de changement de valeur. 
    propertyChangeSupport.firePropertyChange("name", oldName, value);  
}

En invoquant la méthode firePropertyChange() de la classe PropertyChangeSupport nous pouvons prévenir les observateurs enregistrés de la modification de la valeur sur la propriété « name ». Les listeners exclusivement à l’écoute de cette propriété ainsi que les listeners qui se sont enregistrés de manière globale recevront la notification de changement de valeur.

La méthode fireIndexedPropertyChange() permet également de lancer des notifications pour les changements de valeur des propriétés indexées.

Mis à jour le 15 octobre 2015 bouye

Les propriétés de type contrained property ou propriété contrainte sont des propriétés liées dont la modification est sujette à une autorisation par une entité externe qui peut l'interdire ou pas. L'observateur externe doit implémenter l'interface java.beans.VetoableChangeListener et sa méthode vetoableChange() ; cette méthode doit signaler une exception de type java.beans.PropertyVetoException lorsque le changement de valeur de la propriété n'est pas autorisé.

La mise en place dans le bean est similaire à celle du PropertyChangeSupport, mais en utilisant la classe java.beans.VetoableChangeSupport à la place :

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
public class Person { 
  
    [...] 
  
    private final VetoableChangeSupport vetoableChanteSupport = new VetoableChangeSupport(this); 
  
    public void addVetoableChangeListener(VetoableChangeListener listener) { 
        vetoableChanteSupport.addVetoableChangeListener(listener); 
    } 
  
    public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) { 
        vetoableChanteSupport.addVetoableChangeListener(propertyName, listener); 
    } 
  
    public void removeVetoableChangeListener(VetoableChangeListener listener) { 
        vetoableChanteSupport.removeVetoableChangeListener(listener); 
    } 
  
    public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) { 
        vetoableChanteSupport.removeVetoableChangeListener(propertyName, listener); 
    } 
}

Nous pouvons maintenant modifier notre setter comme suit :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
public void setName(String value) throws PropertyVetoException { 
    String oldName = name; 
    // Cette invocation génère une exception si la modification n'est pas autorisée. 
    vetoableChanteSupport.fireVetoableChange("name", oldName, value); 
    // Si aucun veto n'a été levé, on procède à la modification comme auparavant. 
    name = value; 
    // Lancement de la notification de changement de valeur.  
    propertyChangeSupport.firePropertyChange("name", oldName, value); 
}

Mis à jour le 15 octobre 2015 bouye

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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 © 2017 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.

 
Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 -