il y a une règle qui dit:
Les noms représentant des constantes (variables finales) doivent être en majuscules, avec des traits de soulignement pour séparer les mots (extrait de http://geosoft.no/development/javastyle.html )
cela fonctionne très bien pour les types primitifs comme int ou strings:
private static final int MAX_COUNT = 10;
Mais qu'en est-il des types non primitifs? Dans la plupart des cas, j'ai vu ce qui suit:
private static final Logger log = Logger.getLogger(MyClass.class);
ou en singletons, où variable d'instance n'est pas en majuscule.
La question est de savoir quel est le bon moyen de déclarer ces types de variables (telles que log et instance)?
C'est toujours une constante . Voir le JLS pour plus d'informations sur la convention de dénomination des constantes. Mais en réalité, tout est une question de préférence.
Les noms des constantes dans les types d'interface doivent être, et
final
les variables de types de classe peuvent être classiquement, une séquence d'un ou plusieurs mots, acronymes ou abréviations, toutes en majuscules, avec des composants séparés par un tiret bas"_"
personnages. Les noms constants doivent être descriptifs et non abrégés inutilement. Classiquement, ils peuvent être une partie appropriée du discours. Exemples de noms de constantes:MIN_VALUE
,MAX_VALUE
,MIN_RADIX
, etMAX_RADIX
de la classeCharacter
.Un groupe de constantes représentant les valeurs alternatives d'un ensemble ou, moins fréquemment, les bits de masquage dans une valeur entière, est parfois utilement spécifié avec un acronyme commun comme préfixe de nom, comme dans:
interface ProcessStates { int PS_RUNNING = 0; int PS_SUSPENDED = 1; }
L'obscurcissement impliquant des noms constants est rare:
- Les noms de constante n'ont normalement pas de lettres minuscules, ils ne masqueront donc normalement pas les noms de paquetages ou de types, ni les champs ombrés, dont les noms contiennent généralement au moins une lettre minuscule.
- Les noms constants ne peuvent pas masquer les noms de méthodes, car ils sont distingués syntaxiquement.
Le dialogue à ce sujet semble être l'antithèse de la conversation sur la désignation des classes interface
et abstract
. Je trouve cela alarmant et pense que la décision est beaucoup plus profonde que de simplement choisir une convention de nommage et de l’utiliser toujours avec static final
.
Lors de la désignation d'interfaces et de classes abstraites, la convention acceptée a évolué de manière à ne pas préfixer ou ajouter de suffixe à votre abstract class
Ou à votre interface
avec des informations d'identification qui indiqueraient qu'il s'agit d'une autre classe.
public interface Reader {}
public abstract class FileReader implements Reader {}
public class XmlFileReader extends FileReader {}
On dit que le développeur n'a pas besoin de savoir que les classes ci-dessus sont abstract
ou un interface
.
Ma préférence personnelle et ma conviction sont que nous devrions suivre une logique similaire lorsque nous faisons référence à des variables static final
. Au lieu de cela, nous évaluons son utilisation pour déterminer comment le nommer. Il semble que l'argument des majuscules soit quelque chose qui a été adopté à l'aveugle des langages C et C++. À mon avis, cela ne justifie pas de poursuivre la tradition en Java.
Nous devrions nous demander quelle est la fonction de static final
Dans notre propre contexte. Voici trois exemples d'utilisation de static final
Dans différents contextes :
public class ChatMessage {
//Used like a private variable
private static final Logger logger = LoggerFactory.getLogger(XmlFileReader.class);
//Used like an Enum
public class Error {
public static final int Success = 0;
public static final int TooLong = 1;
public static final int IllegalCharacters = 2;
}
//Used to define some static, constant, publicly visible property
public static final int MAX_SIZE = Integer.MAX_VALUE;
}
Pourriez-vous utiliser toutes les majuscules dans les trois scénarios? Absolument, mais je pense que l’on peut soutenir que cela nuirait à l’objectif de chacun. Alors, examinons chaque cas individuellement.
Dans le cas de l'exemple Logger
ci-dessus, le consignateur est déclaré comme privé et ne sera utilisé que dans la classe ou éventuellement dans une classe interne. Même s'il a été déclaré à protected
ou , son utilisation est la même:package
visibilité
public void send(final String message) {
logger.info("Sending the following message: '" + message + "'.");
//Send the message
}
Ici , nous ne nous soucions pas que logger
soit une variable membre static final
. Il pourrait simplement s'agir d'une variable d'instance final
. Nous ne savons pas On n'a pas besoin de savoir. Tout ce que nous avons besoin de savoir, c'est que nous enregistrons le message dans le consignateur fourni par l'instance de classe.
public class ChatMessage {
private final Logger logger = LoggerFactory.getLogger(getClass());
}
Vous ne nommeriez pas cela LOGGER
dans ce scénario, alors pourquoi devriez-vous le nommer en majuscule s'il s'agissait de static final
? Son contexte, ou son intention, est identique dans les deux cas.
Remarque: j’ai inversé ma position sur la visibilité package
car elle ressemble plus à une forme d’accès public
, limitée au niveau package
.
Maintenant, vous pourriez dire, pourquoi utilisez-vous des entiers static final
En tant que enum
? C’est une discussion qui évolue encore et je dirais même semi-controversée, je vais donc essayer de ne pas faire dérailler cette discussion trop longtemps en s’y aventurant. Toutefois, il est suggéré de mettre en œuvre le modèle d’énumération accepté suivant:
public enum Error {
Success(0),
TooLong(1),
IllegalCharacters(2);
private final int value;
private Error(final int value) {
this.value = value;
}
public int value() {
return value;
}
public static Error fromValue(final int value) {
switch (value) {
case 0:
return Error.Success;
case 1:
return Error.TooLong;
case 2:
return Error.IllegalCharacters;
default:
throw new IllegalArgumentException("Unknown Error value.");
}
}
}
Il existe des variantes de ce qui précède qui permettent la conversion explicite de enum->int
Et de int->enum
. Dans le cadre de la diffusion en continu de ces informations sur un réseau, la sérialisation native Java est simplement trop détaillée. Un simple int
, short
ou byte
pourrait économiser une bande passante considérable. Je pourrais plonger dans une comparaison longue et contrastée à propos des avantages et inconvénients de enum
vs static final int
impliquant la sécurité de type , lisibilité, maintenabilité, etc., heureusement, cela sort du cadre de cette discussion.
La ligne du bas est ceci, parfois
static final int
Sera utilisé comme une structure de styleenum
.
Si vous pouvez vous faire accepter que la déclaration ci-dessus est vraie , nous pourrons en discuter avec le style. Lors de la déclaration d'un enum
, le style accepté indique que nous ne faisons pas ce qui suit:
public enum Error {
SUCCESS(0),
TOOLONG(1),
ILLEGALCHARACTERS(2);
}
Au lieu de cela, nous faisons ce qui suit:
public enum Error {
Success(0),
TooLong(1),
IllegalCharacters(2);
}
Si votre bloc d'entiers static final
Sert de enum
lâche, pourquoi devriez-vous utiliser une convention de dénomination différente pour celui-ci? Son contexte, ou son intention, est identique dans les deux cas.
Cette utilisation est peut-être la plus nuageuse et la plus discutable. La constante statique taille est l'exemple d'utilisation le plus fréquent. Java supprime le besoin de sizeof()
, mais il est parfois important de savoir combien d'octets une structure de données occupera.
Par exemple, considérons que vous écrivez ou lisez une liste de structures de données dans un fichier binaire, et le format de ce fichier binaire nécessite que la taille totale du bloc de données soit insérée avant les données réelles. Ceci est courant pour qu'un lecteur sache, quand les données s'arrêtent dans le scénario, qu'il y a plus de données, non liées, qui suivent. Considérez le format de fichier constitué suivant:
File Format: MyFormat (MYFM) for example purposes only
[int filetype: MYFM]
[int version: 0] //0 - Version of MyFormat file format
[int dataSize: 325] //The data section occupies the next 325 bytes
[int checksumSize: 400] //The checksum section occupies 400 bytes after the data section (16 bytes each)
[byte[] data]
[byte[] checksum]
Ce fichier contient une liste d'objets MyObject
sérialisés dans un flux d'octets et écrits dans ce fichier. Ce fichier contient 325 octets d'objets MyObject
, mais sans connaître la taille de chacun MyObject
, vous n'avez aucun moyen de savoir quels octets appartiennent à chacun MyObject
. Donc, vous définissez la taille de MyObject
sur MyObject
:
public class MyObject {
private final long id; //It has a 64bit identifier (+8 bytes)
private final int value; //It has a 32bit integer value (+4 bytes)
private final boolean special; //Is it special? (+1 byte)
public static final int SIZE = 13; //8 + 4 + 1 = 13 bytes
}
La structure de données MyObject
occupera 13 octets lors de son écriture dans le fichier tel que défini ci-dessus. Sachant cela, lors de la lecture de notre fichier binaire, nous pouvons déterminer dynamiquement le nombre d'objets MyObject
suivis dans le fichier:
int dataSize = buffer.getInt();
int totalObjects = dataSize / MyObject.SIZE;
Cela semble être le cas d'utilisation typique et l'argument de toutes les constantes majuscules static final
, Et je conviens que dans ce contexte, toute majuscule a un sens. Voici pourquoi:
Java n'a pas de classe struct
comme le langage C, mais un struct
est simplement une classe avec tous les membres publics et aucun constructeur. C'est simplement une donnée struct
. Donc, vous pouvez déclarer un class
dans struct
comme dans fashion:
public class MyFile {
public static final int MYFM = 0x4D59464D; //'MYFM' another use of all uppercase!
//The struct
public static class MyFileHeader {
public int fileType = MYFM;
public int version = 0;
public int dataSize = 0;
public int checksumSize = 0;
}
}
Permettez-moi de commencer cet exemple en déclarant que, personnellement, je n'analyserais pas de cette manière. Je suggérerais plutôt une classe immuable qui gère l'analyse en interne en acceptant un ByteBuffer
ou les 4 variables comme arguments de constructeur. Cela dit, accéder (définir dans ce cas) les membres de ce struct
ressemblerait à quelque chose comme:
MyFileHeader header = new MyFileHeader();
header.fileType = buffer.getInt();
header.version = buffer.getInt();
header.dataSize = buffer.getInt();
header.checksumSize = buffer.getInt();
Ce ne sont pas static
ou final
, mais ce sont des membres exposés publiquement qui peuvent être définis directement. Pour cette raison, je pense que lorsqu'un membre static final
Est exposé publiquement, il est logique de le mettre entièrement en majuscule. C’est la seule fois où est important pour le distinguer des variables publiques non statiques.
Remarque: même dans ce cas, si un développeur tentait de définir une variable final
, il se heurterait à une erreur IDE ou au compilateur).
En conclusion, la convention que vous choisissez pour les variables static final
Va être votre préférence, mais je crois fermement que le contexte d'utilisation devrait peser lourdement sur votre décision de conception. Ma recommandation personnelle serait de suivre l'une des deux méthodologies suivantes:
[highly subjective; logical]
private
qui ne devrait pas être distinguable d'une variable d'instance private
, donnez-leur un nom identique. tout en minuscule enum
lâche de valeurs static
, nommez-le comme vous le feriez avec un enum
. cas Pascal: initial-cap chaque mot [objective; logical]
La méthodologie 2 concentre essentiellement son contexte sur la visibilité et ne laisse aucune place à l’interprétation.
private
ou protected
, alors il devrait être tout en minuscule .public
ou package
, alors il devrait être tout en majuscule .Voici comment je vois la convention de nommage des variables static final
. Je ne pense pas que ce soit quelque chose qui puisse ou devrait être mis dans une seule prise. Je crois que vous devriez évaluer son intention avant de décider comment le nommer.
Cependant, l'objectif principal doit être d'essayer de rester cohérent tout au long de la portée de votre projet/package. En fin de compte, c'est tout ce que vous avez le contrôle.
(Je m'attends à rencontrer de la résistance, mais espère également recueillir l'appui de la communauté sur cette approche. Quelle que soit votre position, restez poli s'il vous plaît lorsque vous reprenez, critiquez ou applaudissez ce choix de style.)
La langue ne s'en soucie pas. L'important est de respecter les styles et conventions établis du projet sur lequel vous travaillez, afin que les autres responsables (ou vous dans cinq mois) aient la meilleure chance de ne pas être confondus.
Je pense qu'un nom entièrement majuscule pour un objet mutable m'embrouillerait certainement, même si la référence à cet objet était stockée dans un static final
variable.
Eh bien c'est une question très intéressante. Je diviserais les deux constantes de votre question en fonction de leur type. int MAX_COUNT
Est une constante de type primitif alors que Logger log
Est un type non primitif.
Lorsque nous utilisons une constante de types primitifs, nous ne mutons la constante qu'une seule fois dans notre code public static final in MAX_COUNT = 10
Et nous accédons simplement à la valeur de la constante ailleurs for(int i = 0; i<MAX_COUNT; i++)
. C'est la raison pour laquelle nous sommes à l'aise avec l'utilisation de cette convention.
Alors que dans le cas des types non primitifs, bien que nous initialisions la constante dans un seul endroit private static final Logger log = Logger.getLogger(MyClass.class);
, nous sommes supposés muter ou appeler une méthode sur cette constante ailleurs log.debug("Problem")
. Nous, les gars, n'aimons pas mettre un opérateur de point après les caractères majuscules. Après tout, nous devons mettre un nom de fonction après l’opérateur point, qui sera sûrement un nom de casse-chameau. C'est pourquoi LOG.debug("Problem")
semblerait maladroit.
Il en est de même avec les types String
. En général, nous ne mutons pas ou n'appelons pas de méthode sur une constante String
dans notre code. C'est pourquoi nous utilisons la convention de dénomination capital pour un objet de type String
.
Une référence constante à un objet n'est pas une constante, c'est simplement une référence constante à un objet.
private static final
n'est pas ce qui définit ou non quelque chose. C’est juste le moyen Java de définir une constante, mais cela ne signifie pas que tous les private static final
déclaration a été mis là pour définir une constante.
Quand j'écris private static final Logger
Je ne cherche pas à définir une constante, je cherche simplement à définir une référence à un objet qui est private
(il n'est pas accessible depuis d'autres classes), static
( qu’il s’agit d’une variable au niveau de la classe, aucune instance n’est nécessaire) et final
(qui ne peut être attribué qu’une fois). Si cela coïncide avec le chemin Java s'attend à ce que vous déclariez une constante, eh bien, pas de chance, mais cela ne la rend pas constante. Je me moque de ce que le compilateur, sonar , ou n'importe quel Java guru dit. Une valeur constante, comme MILLISECONDS_IN_A_SECOND = 1000
est une chose et une référence constante à un objet en est une autre.
On sait que l'or brille, mais tout ce qui brille n'est pas or.
Il n'y a pas de "bonne" voie - il n'y a que des conventions. Vous avez énoncé la convention la plus commune, et celle que je suis dans mon propre code: tous les finales statiques devraient être en majuscules. J'imagine que d'autres équipes suivent d'autres conventions.
À mon avis, une variable "constante" est souvent un détail d'implémentation et ne justifie pas nécessairement des conventions de dénomination différentes. Cela peut aider à la lisibilité, mais cela peut aussi le blesser dans certains cas.
Ces variables sont des constantes, à savoir private static final
qu'ils soient nommés en majuscule ou non. La convention des majuscules montre simplement qu'il est évident que ces variables doivent être des constantes, mais ce n'est pas obligatoire. j'ai vu
private static final Logger log = Logger.getLogger(MyClass.class);
en minuscule auparavant, et cela me convient car je sais que l’enregistreur n’est utilisé que pour consigner les messages, mais il contrevient à la convention. Vous pouvez soutenir que le nom log
est une sous-convention, je suppose. Mais en général, nommer des constantes en majuscules n'est pas la solution idéale, mais bien la meilleure.
Ne vivez pas fanatiquement avec les conventions que Sun a préparées, faites-vous ce que vous sentez juste pour vous et votre équipe.
Par exemple, voici comment Eclipse le fait, enfreignant la convention. Essayez d'ajouter implements Serializable
et Eclipse demanderont à générer cette ligne pour vous.
Mise à jour: Il y avait des cas spéciaux qui ont été exclus ne le savaient pas. Cependant, je refuse de faire ce que vous et votre équipe semble apte.