371 votes

Quelle est la meilleure façon d'implémenter les constantes en Java ?

J'ai vu des exemples comme celui-ci :

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

et j'ai supposé que je pouvais avoir une classe Constants pour envelopper les constantes, en les déclarant static final. Je ne connais pratiquement rien à Java et je me demande si c'est la meilleure façon de créer des constantes.

1 votes

Juste pour ajouter constantes java : public/privé

0 votes

2voto

davidh Points 107

Quelle est la meilleure façon d'implémenter les constantes en Java ?

Une approche que nous devrions vraiment éviter l'utilisation d'interfaces pour définir des constantes.

Créer une interface spécifiquement pour déclarer des constantes est vraiment la pire des choses : cela va à l'encontre de la raison pour laquelle les interfaces ont été conçues : définir le contrat des méthodes.

Même si une interface existe déjà pour répondre à un besoin spécifique, déclarer les constantes dans ces interfaces n'a vraiment aucun sens car les constantes ne devraient pas faire partie de l'API et du contrat fourni aux classes clientes.


Pour simplifier, nous avons grosso modo 4 approches valables .

Avec static final String/Integer champ :

  • 1) utiliser une classe qui déclare des constantes à l'intérieur mais pas seulement.
  • 1 variante) créer une classe dédiée à la déclaration des constantes uniquement.

Avec Java 5 enum :

  • 2) déclarer l'enum dans une classe à but connexe (donc comme une classe imbriquée).
  • 2 variante) créer l'enum comme une classe autonome (donc définie dans son propre fichier de classe).

TLDR : Quelle est la meilleure méthode et où se trouvent les constantes ?

Dans la plupart des cas, la méthode des enums est probablement plus fine que la méthode des static final String/Integer chemin et personnellement, je pense que le static final String/Integer ne devrait être utilisée que si nous avons de bonnes raisons de ne pas utiliser les enums.
Et sur l'endroit où nous devons déclarer les valeurs constantes, l'idée est de rechercher s'il existe une seule classe existante qui possède une cohésion fonctionnelle spécifique et forte avec des valeurs constantes. Si nous trouvons une telle classe, nous devons l'utiliser comme support de constantes. . Sinon, la constante ne doit être associée à aucune classe particulière.


static final String / static final Integer contre enum

L'utilisation d'Enums est vraiment un moyen à considérer fortement.
Les Enums ont un grand avantage sur String ou Integer champ constant.
Ils fixent une contrainte de compilation plus forte. Si vous définissez une méthode qui prend l'enum comme paramètre, vous ne pouvez passer qu'une valeur d'enum définie dans la classe enum (ou null).
Avec String et Integer, vous pouvez les remplacer par n'importe quelle valeur de type compatible et la compilation se fera sans problème, même si la valeur n'est pas une constante définie dans le fichier static final String / static final Integer champs.

Par exemple, ci-dessous deux constantes définies dans une classe comme static final String champs :

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

Voici une méthode qui s'attend à avoir une de ces constantes comme paramètre :

public void process(String constantExpected){
    ...    
}

Vous pouvez l'invoquer de la manière suivante :

process(MyClass.ONE_CONSTANT);

ou

process(MyClass.ANOTHER_CONSTANT);

Mais aucune contrainte de compilation ne vous empêche de l'invoquer de cette manière :

process("a not defined constant value");

Vous n'aurez l'erreur qu'au moment de l'exécution et seulement si vous effectuez à un moment donné un contrôle sur la valeur transmise.

Avec les enum, les vérifications ne sont pas nécessaires car le client ne peut que passer une valeur enum dans un paramètre enum.

Par exemple, voici deux valeurs définies dans une classe enum (donc constantes d'emblée) :

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

Voici une méthode qui s'attend à avoir une de ces valeurs d'énumération comme paramètre :

public void process(MyEnum myEnum){
    ...    
}

Vous pouvez l'invoquer de la manière suivante :

process(MyEnum.ONE_CONSTANT);

ou

process(MyEnum.ANOTHER_CONSTANT);

Mais la compilation ne vous permettra jamais de l'invoquer de cette manière :

process("a not defined constant value");

Où devons-nous déclarer les constantes ?

Si votre application contient une seule classe existante qui possède une cohésion fonctionnelle spécifique et forte avec les valeurs constantes, le 1) et le 2) semblent plus intuitifs.
En général, l'utilisation des constantes est facilitée si celles-ci sont déclarées dans la classe principale qui les manipule ou qui a un nom très naturel pour deviner que nous la trouverons à l'intérieur.

Par exemple, dans la bibliothèque JDK, les valeurs constantes de l'exponentielle et de pi sont déclarées dans une classe qui déclare non seulement les constantes ( java.lang.Math ).

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

Les clients qui utilisent les fonctions mathématiques s'appuient souvent sur le Math classe. Ainsi, ils peuvent trouver des constantes assez facilement et peuvent également se souvenir où E y PI sont définis de manière très naturelle.

Si votre application ne contient pas une classe existante qui a une cohésion fonctionnelle très spécifique et forte avec les valeurs constantes, les méthodes 1 variante) et 2 variante) semblent plus intuitives.
En général, cela ne facilite pas l'utilisation des constantes si celles-ci sont déclarées dans une classe qui les manipule alors que nous avons aussi 3 ou 4 autres classes qui les manipulent tout autant et aucune de ces classes ne semble plus naturelle que les autres pour accueillir des valeurs constantes.
Dans ce cas, il est judicieux de définir une classe personnalisée pour ne conserver que les valeurs constantes.
Par exemple, dans la bibliothèque JDK, l'élément java.util.concurrent.TimeUnit L'enum n'est pas déclaré dans une classe spécifique car il n'y a pas vraiment une et une seule classe spécifique au JDK qui apparaît comme la plus intuitive pour le contenir :

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

De nombreuses classes déclarées dans java.util.concurrent les utiliser : BlockingQueue , ArrayBlockingQueue<E> , CompletableFuture , ExecutorService ... et aucun d'entre eux ne semble plus approprié pour contenir l'énumération.

1voto

Ryan Delucchi Points 3323

Une constante, de n'importe quel type, peut être déclarée en créant une propriété immuable à l'intérieur d'une classe (c'est-à-dire une variable membre avec l'attribut final modificateur). En général, le static y public sont également fournis.

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

Il existe de nombreuses applications où la valeur d'une constante indique une sélection parmi un n-tuple (par exemple énumération ) de choix. Dans notre exemple, nous pouvons choisir de définir un type énuméré qui limitera les valeurs attribuées possibles (c.-à-d. amélioré sécurité de type ) :

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}

1voto

Une classe de constantes unique et générique est une mauvaise idée. Les constantes doivent être regroupées avec la classe à laquelle elles sont le plus logiquement liées.

Plutôt que d'utiliser des variables de toute sorte (en particulier les enums), je vous suggère d'utiliser des méthodes. Créez une méthode portant le même nom que la variable et demandez-lui de retourner la valeur que vous avez attribuée à la variable. Supprimez ensuite la variable et remplacez toutes les références à celle-ci par des appels à la méthode que vous venez de créer. Si vous pensez que la constante est suffisamment générique pour que vous n'ayez pas à créer une instance de la classe pour l'utiliser, faites de la méthode de la constante une méthode de classe.

1voto

Tim Howland Points 5705

Pour information, une valeur de délai en secondes devrait probablement être un paramètre de configuration (lu dans un fichier de propriétés ou par injection comme dans Spring) et non une constante.

1voto

chandrayya Points 11

Quelle est la différence ?

1.

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2.

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

et en utilisant MyGlobalConstants.TIMEOUT_IN_SECS où nous avons besoin de cette constante. Je pense que les deux sont identiques.

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