Accueil
Rechercher:
sur developpez.com sur les forums
Forums | Tutoriels | F.A.Q's | Participez | Hébergement | Contacts
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi MS-Office SQL & SGBD Oracle  4D  Business Intelligence
FORUMS JAVA FAQs TUTORIELS JAVASEARCH SOURCES LIVRES OUTILS, EDI & API ECLIPSE NETBEANS BLOG DISCUSSIONS TV

Constructeurs et méthodes exportées

Date de publication : 02/08/2006

Par Romain Guy (Gfx) (home)
 



L'invocation depuis un constructeur de méthodes exportées est une faute très commune en Java, et plus généralement en POO. Je le sais très bien puisque je commets cette faute, consciemment toutefois, très régulièrement. Avant de continuer, rappelons qu'une méthode exportée est une méthode publique, protected ou package-private appartenant à une classe non final, c'est-à-dire une méthode qu'une classe fille peut redéfinir.

A première vue, invoquer une méthode exportée depuis le constructeur semble parfaitement valide et même signe d'une bonne conception puisqu'on ne duplique pas d'instructions :
public class BreakMe {
    protected String name;
    protected String cached;

    public BreakMe(String name) {
        setName(name);
    }
    
    public void setName(String name) {
        this.name = name;
        this.cached = name.toUpperCase();
    }
    
    public String getName() {
        return cached;
    }
}
Le code de cette classe très simple conserve en mémoire le nom passé en paramètre ainsi qu'une copie en majuscules. La méthode getName renvoie toujours la copie en majuscules pour forcer les clients de cette API à respecter la casse choisie. L'appel a setName dans le constructeur semble être une bonne solution, surtout si d'autres constructeurs sont ajoutés par la suite. Le code de la méthode n'aura pas a être dupliqué dans chaque constructeur.

Cette classe est malheureusement dangereuse car elle peut mener à l'obtention d'objets à moitié initialisés. Comment cela est-ce possible ? Je vous présente la diabolique classe fille :
public class Breaker extends BreakMe {
    public Breaker(String name) {
        super(name);
    }
    
    public void setName(String name) {
        this.name = "Utah Boy";
    }
    
    public static void main(String... args) {
        Breaker b = new Breaker("Gredin");
        System.out.printf("la longueur du nom est de %s caracteres.",
          b.getName().length());
    }
}
Cette nouvelle classe étend la première pour imposer le nom, malgré le paramètre. Le brouillon qui a rédigé cette classe n'a malheureusement pas lu le code source de la première, ou a été induit en erreur par une mauvaise documentation, et ne réalise que l'opération la plus évidente, l'assignement du champ name. Après exécution du constructeur, le champ cached n'a toujours pas été initialisé et le programme ci-dessus plante misérablement :
gfx@undead /cygdrive/d
$ java Breaker
Exception in thread "main" java.lang.NullPointerException
        at Breaker.main(Breaker.java:12)
Cet exemple est bien sur artificiel et peut être corrigé dans la classe fille en invoquant super.setName("Utah Boy") mais il s'agit d'un cas très simple. De nombreux bugs, parfois subtils, peuvent être provoqués par une conception similaire. La seule solution valable est donc d'interdire dans les constructeurs les appels à des méthodes exportées. Rien ne vous empêche cependant de factoriser votre code : utilisez this(...) pour faire converger les constructeurs vers un seul et unique ou utilisez des méthodes d'initialisations privées.


Articles et tutoriels Java
L'essentiel de Java en une heure
L'API java.nio du JDK 1.4
Inversion de contrôle en Java
L'introspection
Le Java Community Process
Conception de tests unitaires avec JUnit
Les Strings se déchaînent
Présentation de SWT
La programmation réseau en Java avec les sockets
Du bon usage de l'héritage et de la composition
Les références et la gestion de la mémoire en Java
Constructeurs et méthodes exportées en Java
Les membres statiques, finaux et non immuables en Java
Les classes et objets immuables en Java
Comprendre et optimiser le Garbage Collector
Les principes de la programmation d'une interface graphique
Les opérateurs binaires en Java
Prenez le contrôle du bureau avec JDIC
Les Java Data Objects (JDO version 1.0.1)
La persistance des données avec Hibernate 2.1.8
Journalisation avec l'API Log4j
Java 5.0 et les types paramétrés
Les annotations de Java 5
Java 1.5 et les types paramétrés
Créer un moteur de recherche avec Lucene
Articles et tutoriels Swing
Threads et performance avec Swing
Rechercher avec style en utilisant Swing
Splash Screen avec Swing et Java3D
Drag & Drop avec style en utilisant Swing
Attendre avec style en utilisant Swing
Mixer Java3D et Swing
Articles et tutoriels Java Web
Redécouvrez le web avec Wicket

Valid XHTML 1.1!Valid CSS!

Cette création est mise à disposition sous un contrat Creative Commons (Paternité - Partage des Conditions Initiales à l'Identique).
Responsables bénévoles de la rubrique Java : Eric Siber et Baptiste Wicht - Contacter par EMail :
Vos questions techniques : forum d'entraide Java - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright © 2000-2008 www.developpez.com - Legal informations.