248 votes

Un constructeur en Java peut-il être privé ?

Un constructeur peut-il être privé ? En quoi un constructeur privé est-il utile ?

10 votes

Il convient de noter que la plupart des réponses données jusqu'à présent ne considèrent que le cas où l'on a uniquement des constructeurs privés. Vous pouvez avoir des constructeurs publics et privés dans la même classe, pour les raisons expliquées dans la réponse de Michael Aaron Safyan.

0 votes

@ChristianSemrau Je suis en train de regarder le bocal pour lwjgl3 (beta) via Eclipse, et j'ai trouvé un constructeur privé dans le fichier org.lwjgl.Version . Ce qui m'amène ici. Cette classe a aussi sa propre main de manière intéressante. Java est bizarre.

0 votes

Que s'est-il passé quand vous l'avez essayé ? Ou que vous l'avez regardé ? Y avait-il une raison de se méfier de la compilation ou de JLS ?

169voto

Michael Aaron Safyan Points 45071

Oui, un constructeur peut être privé. Il y a différentes utilisations de ceci. L'une de ces utilisations est le singleton anti-modèle de conception que je vous déconseille d'utiliser. Une autre utilisation, plus légitime, est la délégation des constructeurs ; vous pouvez avoir un constructeur qui prend beaucoup d'options différentes qui est vraiment un détail d'implémentation, donc vous le rendez privé, mais ensuite vos autres constructeurs lui sont délégués.

À titre d'exemple de délégation des constructeurs, la classe suivante vous permet d'enregistrer une valeur et un type, mais elle ne vous permet de le faire que pour un sous-ensemble de types. Il est donc nécessaire de rendre le constructeur général privé pour garantir que seuls les types autorisés sont utilisés. Le constructeur privé commun aide à la réutilisation du code.

public class MyClass {
     private final String value;
     private final String type;

     public MyClass(int x){
         this(Integer.toString(x), "int");
     }

     public MyClass(boolean x){
         this(Boolean.toString(x), "boolean");
     }

     public String toString(){
         return value;
     }

     public String getType(){
         return type;
     }

     private MyClass(String value, String type){
         this.value = value;
         this.type = type;
     }
}

Modifier
En regardant cette réponse de plusieurs années plus tard, je voudrais noter que cette réponse est à la fois incomplète et aussi un peu extrême. Les singletons sont en effet un anti-modèle et doivent généralement être évités dans la mesure du possible ; cependant, il existe de nombreuses utilisations des constructeurs privés en dehors des singletons, et ma réponse n'en cite qu'une.

Pour donner quelques autres cas où les constructeurs privés sont utilisés :

  1. Créer une classe non substantielle qui n'est qu'une collection de fonctions statiques liées (il s'agit fondamentalement d'un singleton, mais si elle est sans état et que les fonctions statiques opèrent strictement sur les paramètres plutôt que sur l'état de la classe, ce n'est pas une approche aussi déraisonnable que ce que je suggérais précédemment, bien que l'utilisation d'une interface qui est injectée en fonction des dépendances rende souvent plus facile la maintenance de l'API lorsque l'implémentation nécessite un plus grand nombre de dépendances ou d'autres formes de contexte).

  2. Lorsqu'il existe plusieurs façons de créer l'objet, un constructeur privé peut faciliter la compréhension des différentes façons de le construire (par exemple, celle qui est la plus lisible pour vous ). new ArrayList(5) o ArrayList.createWithCapacity(5) , ArrayList.createWithContents(5) , ArrayList.createWithInitialSize(5) ). En d'autres termes, un constructeur privé vous permet de fournir des fonctions d'usine dont les noms sont plus compréhensibles, et le fait de rendre le constructeur privé garantit que les gens n'utilisent que les noms les plus évidents. Ceci est aussi couramment utilisé avec le modèle du bâtisseur . Par exemple :

    MyClass myVar = MyClass
        .newBuilder()
        .setOption1(option1)
        .setOption2(option2)
        .build();

7 votes

Du point de vue de la testabilité - ils représentent un état global, qui est difficile à prévoir (et à tester)

0 votes

13 votes

@Vuntic, la réponse courte est que les singletons résultent en un état mutable partagé et, plus important encore, l'intégration de l'aspect singleton dans l'API la rend inflexible, difficile à tester et rend les choses difficiles lorsqu'il s'avère que l'hypothèse du singleton n'est pas correcte. S'il est bon d'avoir des singletons dans le sens où vous n'instanciez l'objet qu'une seule fois, l'application du caractère singleton via un constructeur privé et une fonction d'instanciation statique conduit à une conception incroyablement désordonnée et fragile. Une meilleure approche consiste à transmettre l'interface à laquelle le singleton se conforme...

110voto

Bozho Points 273663

Je m'attendais à ce que quelqu'un l'ait mentionné (le 2ème point), mais il y a trois utilisations des constructeurs privés :

  • pour empêcher l'instanciation en dehors de l'objet, dans les cas suivants :

    • singleton
    • méthode d'usine
    • classe de méthodes statiques uniquement (utilitaire)
    • classe de constantes seulement
      .
  • pour éviter la sublcassation (extension). Si vous n'avez qu'un constructeur privé, aucune classe ne peut étendre votre classe, car elle ne peut pas appeler le constructeur de la classe. super() Constructeur. Il s'agit en quelque sorte d'un synonyme de final

  • Constructeurs surchargés - en raison de la surcharge des méthodes et des constructeurs, certains peuvent être privés et d'autres publics. En particulier dans le cas où il y a une classe non publique que vous utilisez dans vos constructeurs, vous pouvez créer un constructeur public qui crée une instance de cette classe et la passe ensuite à un constructeur privé.

10 votes

En Java, le mot clé "final" est utilisé pour empêcher le sous-classement ; il n'est pas nécessaire de rendre le constructeur privé pour cela.

12 votes

Ce n'est pas nécessaire, mais vous pouvez le faire. J'ai mentionné le final comme moyen d'y parvenir.

1 votes

Les "cas suivants" sont nécessairement incomplets mais en tout cas non pertinents. Il empêche l'instanciation à partir de l'extérieur du classe, sur tous des cas, pas seulement ceux énumérés ici.

27voto

Feanor Points 1754

Oui, c'est possible. Un constructeur privé existerait pour empêcher l'instanciation de la classe, ou parce que la construction ne se fait qu'en interne, par exemple dans le cas du modèle Factory. Voir ici pour plus d'informations.

18voto

lavinio Points 12592

Oui.

Cela vous permet de contrôler la façon dont la classe est instanciée. Si vous rendez le constructeur privé, puis créez une méthode de constructeur visible qui renvoie des instances de la classe, vous pouvez faire des choses comme limiter le nombre de créations (typiquement, garantir qu'il y a exactement une instance) ou recycler des instances ou d'autres tâches liées à la construction.

Faire new x() ne revient jamais null mais en utilisant le modèle de l'usine, vous pouvez rendre null ou même de renvoyer des sous-types différents.

Vous pouvez également l'utiliser pour une classe qui n'a pas de membres d'instance ou de propriétés, seulement des membres statiques, comme dans une classe de fonction utilitaire.

0 votes

Mais vous pouvez garder la trace du nombre d'instances en utilisant simplement une variable statique ; il n'est pas nécessaire de rendre le constructeur privé pour cela.

1 votes

@michael en effet vous pouvez, mais ce n'est pas aussi élégant, et la restriction n'est pas aussi évidente pour les utilisateurs de la classe.

1 votes

@Jon, désolé, j'ai mal compris... Je pensais que vous ne faisiez que compter le nombre d'instances, et non pas restreindre le nombre d'instances.

10voto

lichenbo Points 375

Eh bien, si toutes les méthodes d'une classe sont statiques, un constructeur privé est une bonne idée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X