2010-04-30 4 views
14

En ce moment je pense à ajouter un constructeur privé à une classe qui ne contient que String constantes.Utilisation du constructeur privé pour empêcher l'instanciation de la classe?

public class MyStrings { 
    // I want to add this: 
    private MyString() {} 

    public static final String ONE = "something"; 
    public static final String TWO = "another"; 
    ... 
} 

Y at-il des performances ou mémoire frais généraux si j'ajoute un constructeur privé à cette classe pour empêcher quelqu'un pour instancier?

Pensez-vous qu'il est nécessaire du tout ou que les constructeurs privés à cet effet sont une perte de temps et l'encombrement de code?

MISE À JOUR

Je vais pour une classe finale avec constructeur privé et un javadoc descriptif pour la classe. Je ne peux pas utiliser ENUM (que je préfère) car je suis coincé sur Java 1.4 pour le moment. Ce serait ma modification:

/** 
* Only for static access, do not instantiate this class. 
*/ 
public final class MyStrings { 
    private MyString() {} 

    public static final String ONE = "something"; 
    public static final String TWO = "another"; 
    ... 
} 
+0

Le bloc UPDATE est une réponse – 030

Répondre

7

L'utilisation du constructeur privé pour empêcher l'instanciation de la classe?

Il y a plusieurs façons dont vous pouvez penser des utilisateurs empêchant de la Instantiations dans le but de créer les Constantes

  1. Comme vous l'avez mentionné une classe avec les constructeurs privés et a toutes les cordes Constantes, est l'un ainsi, même il ia une surcharge, qui peut être négligeable
  2. que vous pouvez créer une classe avec final Modidifier et définir votre chaîne constantes
  3. vous pouvez utiliser la classe abstraite avec la chaîne Constantes
  4. Vous pouvez définir les constantes de chaîne dans les fichiers de propriétés et y accéder, cela réduira définitivement la mémoire et augmentera la flexibilité de votre code.
0

Un constructeur public synthétique aurait été généré de toute façon. Donc non.

vraiment quelques octets sur des centaines de millions à l'exécution ne va pas faire beaucoup de différence.

Je suggère également faire la classe final et juste pour être complet ont le constructeur lancer une exception.

Si vous voulez le code source laconique, vous pouvez créer un ENUM sans valeurs. Cela pourrait causer une certaine confusion avec les programmeurs débutants.

+1

Java uniquement un constructeur synthèse du public par défaut s'il y a * pas * autres. Un constructeur privé empêche la génération de la valeur par défaut. –

2

Je préfère utiliser une énumération pour conserver cette chaîne. Cela garantirait que, quel que soit l'endroit où vous utilisez ces chaînes, vous ne soyez transmis que dans l'une des chaînes autorisées.

0

C'est la bonne façon de stocker certaines constantes, comme le suggère dans Effective Java (2e éd.), Point 19.

1

Si votre classe ne compte que des membres statiques, alors il n'y a pas besoin d'avoir un privé ou constructeur public. Tous les membres sont accessibles même sans objet. En fait, je trouve déroutant d'avoir un constructeur dans un tel cas.

+10

Si vous n'avez pas de constructeur du tout, le compilateur vous en fournira un - qui sera public, permettant aux gens de construire une instance. Le but d'un constructeur privé est d'empêcher cela. –

+1

@Jon qui dans le scénario fourni n'a aucun point étant donné que tous les membres sont statiques et finaux. Il n'y a pas grand-chose à faire avec une instance de cette classe, donc l'empêcher d'être instancié est un OMI inutile. Eh bien, cela empêche quelqu'un d'utiliser une classe étendue, mais une classe 'final' résout cela. – jweyrich

+4

@jweyrich: Le but de l'empêcher d'être instancié est que vous ne devriez pas * permettre * aux utilisateurs de faire quelque chose qui est inutile. (C'est pourquoi les classes statiques existent en C#.) S'il n'y a aucune raison de jamais créer une instance de la classe, votre code devrait l'empêcher de se produire. Un simple constructeur privé avec un commentaire de "// empêcher l'instanciation" est bien IMO. –

5

Si vous ne serez pas à quiconque de faire un objet de la classe que vous pouvez faire ce abstrait comme celui-ci

public abstract class MyStrings { 
    public static final String ONE = "something"; 
    public static final String TWO = "another"; 
} 

et accéder à vos variables statiques comme celui-ci

String val1 = MyStrings.ONE; 
String val2 = MyStrings.TWO; 

Je pense Ce serait une meilleure solution.

+2

Mais vous pouvez toujours étendre la classe, ce qui pourrait être évité dans une classe finale. L'ajout du constructeur privé empêchera également les instances et vous aurez terminé. –

+0

Oui, vous avez raison de dire qu'il peut être prolongé, vous avez un point là-bas. Je n'ai pas à ce sujet, belle solution avec la classe finale et le constructeur privé. – jweber

+0

Je voudrais aller avec cette approche. Si quelqu'un a pris la peine d'étendre la classe abstraite et de l'instancier, il doit avoir une très bonne raison de le faire. –

6

Vous pouvez ajouter un constructeur privé, mais il existe deux autres options.

Dans la même situation, j'utiliseraient un recenseur.S'il est logique de votre implémentation, vous pouvez utiliser à la place, si elle est public ou private dépend de l'endroit où vous devez l'utiliser:

public enum MyStrings { 

    ONE ("something"), 

    TWO ("something else"); 

    private String value; 

    private MyStrings(String str) { 
    this.value = str; 
    } 

} 

Une autre option serait de le mettre dans une classe, ceux qui ne peuvent pas abstract instancier:

public abstract MyStrings { 

    public static final String STUFF = "stuff"; 
    public static final String OTHER = "other stuff"; 
} 

accès pour les travaux recenseur et classe abstraite comme la mise en œuvre que vous avez présenté:

MyStrings.STUFF 
+1

Je pense aussi que l'utilisation d'une énumération est le chemin à suivre ici. Je remplacerais également la méthode toString. – Eldelshell

+0

Ah, j'ai oublié de mentionner que cette classe est utilisée avec Java 1.4. Je voudrais l'avoir dans 1.5+, mais vous savez, vous n'obtenez pas toujours ce que vous voulez ... ;-) J'irais pour l'ENUM et une classe finale avec une version plus récente de Java aussi . – cringe

2

Il n'y a pas de surcharge de performances ou de mémoire si vous ajoutez un constructeur privé dans ce cas. De plus, il n'est pas nécessaire puisque vos variables statiques publiques sont partagées entre toutes les instances de votre objet.

0

Pour moi, la meilleure explication est efficace livre Java: Point 4: Faire respecter noninstantiability avec un constructeur privé (See more)

En résumé:

  • constructeur privé est due Les classes d'utilitaire n'ont pas été conçues pour être instanciées, de même qu'une décision de conception. (AUCUNE performance ou charge de mémoire)
  • La création d'un résumé de classe ne fonctionne pas car il peut être sous-classé puis instancié.
  • Avec une classe abstraite, l'utilisateur peut penser que la classe est destinée à l'héritage.
  • La seule façon de s'assurer qu'aucune instanciation est d'ajouter un private constructor qui garantit que le constructeur par défaut n'est pas généré.
  • Le constructeur privé empêche l'héritage car le super constructeur ne peut pas être appelé (donc il n'est pas nécessaire de déclarer la classe comme finale)
  • Lancer une erreur dans le constructeur privé évite de l'appeler dans la classe.

definetively, la meilleure façon serait quelque chose comme suivant:

public class MyStrings { 

    private MyStrings() { 
     throw new AssertionError(); 
    } 
     ... 
} 
Questions connexes