J'ai vu des exemples comme celui-ci:
public class MaxSeconds {
public static final int MAX_SECONDS = 25;
}
et supposé que je pourrais avoir une classe Constantes pour envelopper les constantes, les déclarant statiques finales. Je ne connais pratiquement pas Java du tout et je me demande si c'est la meilleure façon de créer des constantes.
Réponses:
C'est parfaitement acceptable, probablement même la norme.
où
TYPE
est le type,NAME
est le nom dans toutes les majuscules avec des soulignements pour les espaces, etVALUE
est la valeur constante;Je recommande fortement de NE PAS mettre vos constantes dans leurs propres classes ou interfaces.
En remarque: les variables déclarées finales et mutables peuvent toujours être modifiées; cependant, la variable ne peut jamais pointer vers un objet différent.
Par exemple:
C'est légal et ce
ORIGIN
serait alors un point à (3, 0).la source
Je déconseille fortement d'avoir une seule classe de constantes. Cela peut sembler une bonne idée à l'époque, mais lorsque les développeurs refusent de documenter les constantes et que la classe se développe pour englober plus de 500 constantes qui ne sont pas du tout liées les unes aux autres (étant liées à des aspects entièrement différents de l'application), cela se transforme généralement en un fichier de constantes complètement illisible. Au lieu:
la source
C'est une MAUVAISE PRATIQUE d'utiliser des interfaces juste pour contenir des constantes (appelé motif d'interface constant par Josh Bloch). Voici ce que conseille Josh:
Exemple:
À propos de la convention de dénomination:
la source
abstract
notation pour la classe plutôt que le constructeur privé.abstract
au lieu d'un constructeur privé n'empêche pas complètement l'instanciation, car on pourrait la sous-classer et instancier la sous-classe (non pas que ce soit une bonne idée de le faire, mais c'est possible). @ToolmakerSteve Vous ne pouvez pas sous-classer une classe avec un constructeur privé (du moins pas sans un gros mauvais hack), car le constructeur de la sous-classe doit appeler le constructeur (désormais privé) de sa superclasse. Donc, le marquerfinal
est inutile (mais peut-être plus explicite).Dans Effective Java (2e édition), il est recommandé d'utiliser des énumérations au lieu d'entiers statiques pour les constantes.
Il y a une bonne description des énumérations en Java ici: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
Notez qu'à la fin de cet article, la question posée est:
Avec une réponse de:
la source
Évitez simplement d'utiliser une interface:
Il est tentant, mais viole l'encapsulation et brouille la distinction des définitions de classe.
la source
J'utilise l'approche suivante:
Que, par exemple, j'utilise
Constants.DB.Connection.URL
pour être constant. Il me semble plus "orienté objet" que pour moi.la source
La création de constantes finales statiques dans une classe distincte peut vous poser des problèmes. Le compilateur Java optimisera réellement cela et placera la valeur réelle de la constante dans n'importe quelle classe qui la référence.
Si vous modifiez plus tard la classe 'Constants' et que vous ne recompilez pas dur sur d'autres classes qui référencent cette classe, vous vous retrouverez avec une combinaison d'anciennes et de nouvelles valeurs utilisées.
Au lieu de les considérer comme des constantes, considérez-les comme des paramètres de configuration et créez une classe pour les gérer. Faites en sorte que les valeurs ne soient pas définitives et envisagez même d'utiliser des getters. À l'avenir, comme vous déterminerez que certains de ces paramètres devraient être configurables par l'utilisateur ou l'administrateur, ce sera beaucoup plus facile à faire.
la source
L'erreur numéro un que vous pouvez faire est de créer une classe accessible à l'échelle mondiale appelée avec un nom générique, comme les constantes. Cela est simplement jonché d'ordures et vous perdez toute capacité à déterminer quelle partie de votre système utilise ces constantes.
Au lieu de cela, les constantes doivent entrer dans la classe qui les "possède". Avez-vous une constante appelée TIMEOUT? Il devrait probablement aller dans votre classe Communications () ou Connection (). MAX_BAD_LOGINS_PER_HOUR? Va dans Utilisateur (). Et ainsi de suite.
L'autre utilisation possible est les fichiers Java .properties lorsque des "constantes" peuvent être définies au moment de l'exécution, mais pas facilement modifiables par l'utilisateur. Vous pouvez les empaqueter dans vos .jars et les référencer avec le Class resourceLoader.
la source
C'est la bonne façon de procéder.
Généralement, les constantes ne sont pas conservées dans des classes "Constantes" distinctes car elles ne sont pas détectables. Si la constante est pertinente pour la classe actuelle, les garder là aide le développeur suivant.
la source
Et une énumération?
la source
Je préfère utiliser des getters plutôt que des constantes. Ces getters peuvent retourner des valeurs constantes, par exemple
public int getMaxConnections() {return 10;}
, mais tout ce qui a besoin de la constante passera par un getter.Un avantage est que si votre programme dépasse la constante - vous trouvez qu'il doit être configurable - vous pouvez simplement changer la façon dont le getter renvoie la constante.
L'autre avantage est que pour modifier la constante, vous n'avez pas à recompiler tout ce qui l'utilise. Lorsque vous référencez un champ final statique, la valeur de cette constante est compilée dans tout bytecode qui la référence.
la source
Je suis d'accord que l'utilisation d'une interface n'est pas la voie à suivre. Éviter ce modèle a même son propre élément (# 18) dans Bloch's Effective Java .
Un argument avancé par Bloch contre le modèle d'interface constante est que l'utilisation de constantes est un détail d'implémentation, mais l'implémentation d'une interface pour les utiliser expose ce détail d'implémentation dans votre API exportée.
Le
public|private static final TYPE NAME = VALUE;
modèle est un bon moyen de déclarer une constante. Personnellement, je pense qu'il vaut mieux éviter de faire une classe séparée pour héberger toutes vos constantes, mais je n'ai jamais vu de raison de ne pas le faire, à part les préférences et le style personnels.Si vos constantes peuvent être bien modélisées comme une énumération, considérez la structure d' énumération disponible dans 1.5 ou version ultérieure.
Si vous utilisez une version antérieure à 1.5, vous pouvez toujours retirer les énumérations de typeafe en utilisant des classes Java normales. (Voir ce site pour en savoir plus).
la source
Sur la base des commentaires ci-dessus, je pense que c'est une bonne approche pour changer la classe constante globale à l'ancienne (ayant des variables finales statiques publiques) en son équivalent enum d'une manière comme ceci:
Alors je peux les référer à aimer:
la source
Une bonne conception orientée objet ne devrait pas nécessiter de nombreuses constantes accessibles au public. La plupart des constantes doivent être encapsulées dans la classe qui en a besoin pour faire son travail.
la source
Il y a une certaine opinion pour y répondre. Pour commencer, les constantes en java sont généralement déclarées publiques, statiques et finales. Voici les raisons:
Je n'utiliserais jamais une interface pour un accesseur / objet CONSTANTS simplement parce que les interfaces devraient généralement être implémentées. Cela ne serait-il pas drôle:
Au lieu de cela, je choisirais entre plusieurs façons différentes, en fonction de certains petits compromis, et cela dépend donc de ce dont vous avez besoin:
la source
Une approche que nous devons vraiment éviter : utiliser des interfaces pour définir des constantes.
Créer une interface spécifiquement pour déclarer des constantes est vraiment la pire des choses: cela vainc la raison pour laquelle les interfaces ont été conçues: définir le contrat de méthode (s).
Même si une interface existe déjà pour répondre à un besoin spécifique, y déclarer les constantes 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 globalement 4 approches valides .
Avec
static final String/Integer
champ:Avec
Java 5 enum
:TLDR: Quelle est la meilleure façon et où localiser les constantes?
Dans la plupart des cas, la méthode enum est probablement plus fine que la
static final String/Integer
méthode et personnellement, je pense que lastatic final String/Integer
méthode ne doit être utilisée que si nous avons de bonnes raisons de ne pas utiliser les énumérations.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
contreenum
L'utilisation des énumérations est vraiment un moyen à prendre en considération.
Énumérations ont un grand avantage sur
String
ouInteger
champ constant.Ils définissent une contrainte de compilation plus forte. Si vous définissez une méthode qui prend l'énumération en paramètre, vous ne pouvez transmettre qu'une valeur d'énumération 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 passera bien même si la valeur n'est pas une constante définie dans les champs
static final String
/static final Integer
.Par exemple, sous deux constantes définies dans une classe en tant que
static final String
champs:Voici une méthode qui s'attend à avoir une de ces constantes comme paramètre:
Vous pouvez l'invoquer de cette façon:
ou
Mais aucune contrainte de compilation ne vous empêche de l'invoquer de cette façon:
Vous auriez l'erreur uniquement lors de l'exécution et uniquement si vous effectuez à la fois une vérification de la valeur transmise.
Avec enum, les vérifications ne sont pas nécessaires car le client ne peut transmettre qu'une valeur enum dans un paramètre enum.
Par exemple, voici deux valeurs définies dans une classe enum (donc constante hors de la boîte):
Voici une méthode qui s'attend à avoir l'une de ces valeurs d'énumération comme paramètre:
Vous pouvez l'invoquer de cette façon:
ou
Mais la compilation ne vous permettra jamais de l'invoquer de cette façon:
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) apparaissent plus intuitifs.
Généralement, cela facilite l'utilisation des constantes 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 les trouverons à l'intérieur.
Par exemple, dans la bibliothèque JDK, les valeurs exponentielles et constantes pi sont déclarées dans une classe qui déclare non seulement des déclarations constantes (
java.lang.Math
).Les clients utilisant des fonctions mathématiques comptent souvent sur la
Math
classe. Ainsi, ils peuvent trouver des constantes assez facilement et peuvent également se rappeler oùE
etPI
sont définis de manière très naturelle.Si votre application ne contient pas de classe existante qui a une cohésion fonctionnelle très spécifique et forte avec les valeurs constantes, les manières 1 variante) et 2 variante) apparaissent plus intuitives.
Généralement, 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 autant et qu'aucune de ces classes ne semble plus naturelle que les autres pour hôtes valeurs constantes.
Ici, définir une classe personnalisée pour ne contenir que des valeurs constantes est logique.
Par exemple, dans la bibliothèque JDK, l'
java.util.concurrent.TimeUnit
énumération n'est pas déclarée dans une classe spécifique car il n'y a pas vraiment une et une seule classe spécifique JDK qui apparaît comme la plus intuitive pour la contenir:De nombreuses classes déclarées dans les
java.util.concurrent
utiliser:BlockingQueue
,ArrayBlockingQueue<E>
,CompletableFuture
,ExecutorService
, ... et vraiment pas l' un d'eux semble plus approprié de tenir le ENUM.la source
Une constante, de tout type, peut être déclarée en créant une propriété immuable dans une classe (c'est-à-dire une variable membre avec le
final
modificateur). En règle générale, les modificateursstatic
etpublic
sont également fournis.Il existe de nombreuses applications où la valeur d'une constante indique une sélection à partir d'un n-tuple (par exemple, une énumération ) de choix. Dans notre exemple, nous pouvons choisir de définir un type énuméré qui restreindra les valeurs attribuées possibles (c'est -à- dire une sécurité de type améliorée ):
la source
Une seule classe de constantes génériques 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 nature (en particulier des énumérations), 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 renvoyer la valeur que vous avez affectée à la variable. Supprimez maintenant 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 ne deviez pas avoir à créer une instance de la classe juste pour l'utiliser, faites de la méthode constante une méthode de classe.
la source
FWIW, une valeur de délai d'expiration 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.
la source
Quelle est la différence
1.
2.
et en utilisant
MyGlobalConstants.TIMEOUT_IN_SECS
partout où nous avons besoin de cette constante. Je pense que les deux sont identiques.la source
Je n'appellerais pas la classe la même (à part le casse) que la constante ... J'aurais au moins une classe de "Paramètres", ou "Valeurs", ou "Constantes", où toutes les constantes vivraient. Si j'en ai un grand nombre, je les regrouperais en classes logiques constantes (UserSettings, AppSettings, etc.)
la source
Pour aller plus loin, vous pouvez placer des constantes utilisées globalement dans une interface afin qu'elles puissent être utilisées à l'échelle du système. Par exemple
Mais ne l'implémentez pas. Il suffit de s'y référer directement dans le code via le nom de classe complet.
la source
Pour les constantes, Enum est un meilleur choix à mon humble avis. Voici un exemple
classe publique myClass {
la source
L'une des façons dont je le fais est de créer une classe «globale» avec les valeurs constantes et d'effectuer une importation statique dans les classes qui ont besoin d'accéder à la constante.
la source
static final
est ma préférence, je n'utiliserais unenum
si l'article était en effet énumérable.la source
j'utilise
static final
pour déclarer des constantes et aller avec la notation de nommage ALL_CAPS. J'ai vu pas mal d'instances réelles où toutes les constantes sont regroupées dans une interface. Quelques articles ont à juste titre qualifié cela de mauvaise pratique, principalement parce que ce n'est pas le rôle d'une interface. Une interface doit appliquer un contrat et ne doit pas être un endroit pour insérer des constantes non liées. Le regrouper dans une classe qui ne peut pas être instanciée (via un constructeur privé) est également très bien si la sémantique constante n'appartient pas à une classe spécifique ( es). Je mets toujours une constante dans la classe à laquelle elle est la plus liée, car cela a du sens et est également facilement maintenable.Les énumérations sont un bon choix pour représenter une plage de valeurs, mais si vous stockez des constantes autonomes en mettant l'accent sur la valeur absolue (par exemple TIMEOUT = 100 ms), vous pouvez simplement opter pour l'
static final
approche.la source
Je suis d'accord avec ce que la plupart disent, il est préférable d'utiliser des énumérations lorsqu'il s'agit d'une collection de constantes. Cependant, si vous programmez sous Android, il existe une meilleure solution: IntDef Annotation .
L'annotation IntDef est supérieure aux énumérations d'une manière simple, elle prend beaucoup moins de place car elle est simplement un marqueur de compilation. Ce n'est pas une classe, ni la propriété de conversion de chaîne automatique.
la source
C'est une mauvaise habitude et une pratique terriblement ennuyeuse de citer Joshua Bloch sans comprendre le fondamentalisme fondamental zéro.
Je n'ai rien lu Joshua Bloch, donc soit
Comme dans l'intégrisme biblique, toutes les lois bibliques peuvent être résumées par
et de même le fondamentalisme du génie logiciel peut être résumé par
De plus, parmi les cercles fondamentalistes bibliques, un corollaire fort et raisonnable est établi
De même, si vous ne vous respectez pas en tant que programmeur et acceptez simplement les déclarations et les prophéties de certains gourous de la programmation SANS remettre en question les principes fondamentaux, vos citations et votre confiance en Joshua Bloch (et autres) n'ont aucun sens. Et par conséquent, vous n'auriez en fait aucun respect pour vos collègues programmeurs.
Les lois fondamentales de la programmation logicielle
Les constantes de modèle d'interface sont une mauvaise habitude ???
En vertu de quelles lois de programmation fondamentalement efficace et responsable tombe cet édit religieux?
Lisez simplement l'article de wikipedia sur les constantes de modèle d'interface ( https://en.wikipedia.org/wiki/Constant_interface ), et les excuses idiotes qu'il énonce contre les constantes de modèle d'interface.
Whatif-No IDE? Qui sur terre en tant que programmeur logiciel n'utiliserait pas un IDE? La plupart d'entre nous sont des programmeurs qui préfèrent ne pas avoir à prouver leur survie au machisme aescétique en évitant l'utilisation d'un IDE.
Pollue l'espace de noms avec des variables non utilisées dans la portée actuelle? Il pourrait être partisan de cette opinion
L'utilisation d'interfaces pour appliquer des constantes est un abus d'interfaces. Ses partisans ont la mauvaise habitude de
Il est difficile, voire impossible, de convertir des interfaces en classes implémentées à l'avenir. Hah .... hmmm ... ???
Quelles que soient les excuses, il n’existe AUCUNE EXCUSE VALABLE en matière de génie logiciel FONDAMENTALEMENT EFFICACE pour délégitimer ou décourager généralement l’utilisation de constantes d’interface.
Peu importe les intentions et les états mentaux d'origine des pères fondateurs qui ont élaboré la Constitution des États-Unis. Nous pourrions débattre des intentions originales des pères fondateurs, mais tout ce qui m'importe, ce sont les déclarations écrites de la Constitution américaine. Et il est de la responsabilité de chaque citoyen américain d'exploiter l'intégrisme littéraire écrit, et non les intentions fondatrices non écrites, de la Constitution américaine.
De même, je me fiche de ce que les intentions "originales" des fondateurs de la plate-forme Java et du langage de programmation avaient pour l'interface. Ce qui m'importe, ce sont les fonctionnalités efficaces fournies par la spécification Java, et j'ai l'intention d'exploiter ces fonctionnalités au maximum pour m'aider à respecter les lois fondamentales de la programmation logicielle responsable. Peu m'importe si je suis perçu comme "violant l'intention des interfaces". Peu m'importe ce que Gosling ou quelqu'un Bloch dit à propos de la "bonne façon d'utiliser Java", à moins que ce qu'ils disent ne viole pas mon besoin de fondamentaux épanouissants et EFFICACES.
L'essentiel est la normalisation du modèle de données
Peu importe comment votre modèle de données est hébergé ou transmis. Que vous utilisiez des interfaces ou des énumérations ou des whatevernots, relationnels ou sans SQL, si vous ne comprenez pas le besoin et le processus de normalisation du modèle de données.
Nous devons d'abord définir et normaliser le modèle de données d'un ensemble de processus. Et lorsque nous avons un modèle de données cohérent, SEULEMENT alors nous pouvons utiliser le flux de processus de ses composants pour définir le comportement fonctionnel et le processus bloque un champ ou un domaine d'applications. Et c'est seulement alors que nous pourrons définir l'API de chaque processus fonctionnel.
Même les facettes de la normalisation des données telles que proposées par EF Codd sont maintenant sérieusement mises à l'épreuve et sévèrement mises à l'épreuve. Par exemple, sa déclaration sur 1NF a été critiquée comme ambiguë, mal alignée et trop simplifiée, tout comme le reste de ses déclarations, en particulier avec l'avènement des services de données modernes, des technologies de prise en charge et de la transmission. OMI, les déclarations EF Codd devraient être complètement abandonnées et un nouvel ensemble de déclarations plus plausibles mathématiquement devrait être conçu.
Une faille flagrante d'EF Codd et la cause de son mauvais alignement sur une compréhension humaine efficace est sa conviction que les données multidimensionnelles et mutables perceptibles humainement peuvent être efficacement perçues à travers un ensemble de mappages bidimensionnels fragmentaires.
Les fondements de la normalisation des données
Ce qu'EF Codd n'a pas exprimé.
Au sein de chaque modèle de données cohérent, il s'agit de l'ordre séquentiel gradué de cohérence du modèle de données à atteindre.
Dans un domaine ou une grille d'applications de composants inter-services, il doit y avoir un et un seul modèle de données cohérent ou il existe un moyen pour un modèle / version de données de s'identifier.
Demandons-nous toujours si nous pourrions utiliser des constantes d'interface? Vraiment ?
Des problèmes de normalisation des données sont en jeu plus importants que cette question banale. SI vous ne résolvez pas ces problèmes, la confusion que vous pensez que les constantes d'interface provoquent n'est comparativement rien. Rien.
À partir de la normalisation du modèle de données, vous déterminez les composants en tant que variables, propriétés, constantes d'interface de contrat.
Ensuite, vous déterminez ce qui entre dans l'injection de valeur, la conservation de la configuration des propriétés, les interfaces, les chaînes finales, etc.
Si vous devez utiliser l'excuse de devoir localiser un composant plus facilement à dicter par rapport aux constantes d'interface, cela signifie que vous avez la mauvaise habitude de ne pas pratiquer la normalisation du modèle de données.
Vous souhaitez peut-être compiler le modèle de données dans une version vcs. Que vous pouvez extraire une version distinctement identifiable d'un modèle de données.
Les valeurs définies dans les interfaces sont totalement assurées d'être non modifiables. Et partageable. Pourquoi charger un ensemble de chaînes finales dans votre classe à partir d'une autre classe alors que tout ce dont vous avez besoin est cet ensemble de constantes ??
Alors pourquoi ne pas publier un contrat de modèle de données? Je veux dire si vous pouvez le gérer et le normaliser de manière cohérente, pourquoi pas? ...
Maintenant, je peux référencer les libellés contractés de mes applications de manière telle que
Cela confond le contenu du fichier jar? En tant que programmeur Java, je ne me soucie pas de la structure du pot.
Cela présente de la complexité pour les échanges d'exécution motivés par osgi? Osgi est un moyen extrêmement efficace pour permettre aux programmeurs de continuer dans leurs mauvaises habitudes. Il existe de meilleures alternatives que l'osgi.
Ou pourquoi pas ça? Il n'y a aucune fuite des constantes privées dans le contrat publié. Toutes les constantes privées doivent être regroupées dans une interface privée nommée "Constantes", car je ne veux pas avoir à rechercher de constantes et je suis trop paresseux pour taper à plusieurs reprises "chaîne finale privée".
Peut-être même ceci:
Le seul problème avec les constantes d'interface mérite d'être pris en compte, c'est quand l'interface est implémentée.
Ce n'est pas "l'intention originale" des interfaces? Comme si je me soucierais de "l'intention originale" des pères fondateurs dans l'élaboration de la Constitution américaine, plutôt que de la façon dont la Cour suprême interpréterait les lettres écrites de la Constitution américaine ???
Après tout, je vis au pays du libre, du sauvage et de la maison des braves. Soyez courageux, libre, sauvage, utilisez l'interface. Si mes collègues programmeurs refusent d'utiliser des moyens de programmation efficaces et paresseux, suis-je obligé par la règle d'or de réduire mon efficacité de programmation pour l'aligner avec la leur? Je devrais peut-être le faire, mais ce n'est pas une situation idéale.
la source