Le dialogue sur ce sujet semble être l'antithèse de la conversation sur l'attribution de noms. interface
y abstract
classes. Je trouve cela alarmant, et je pense que la décision est bien plus profonde que le simple fait de choisir une convention de dénomination et de l'utiliser systématiquement avec les classes. static final
.
Abstrait et interface
Lors de la dénomination d'interfaces et de classes abstraites, la convention acceptée a évolué pour ne pas préfixer ou suffixer le nom de votre abstract class
ou interface
avec toute information d'identification qui indiquerait que c'est autre chose qu'une classe.
public interface Reader {}
public abstract class FileReader implements Reader {}
public class XmlFileReader extends FileReader {}
Il est dit que le développeur n'a pas besoin de savoir que les classes ci-dessus sont abstract
ou un interface
.
Static Final
Ma préférence personnelle et ma conviction sont que nous devrions suivre une logique similaire lorsque nous nous référons à static final
variables. Au lieu de cela, nous évaluons son utilisation pour déterminer comment la nommer. Il semble que l'argument des majuscules ait été adopté aveuglément par les langages C et C++. À mon avis, cela ne justifie pas de poursuivre cette tradition en Java.
Question d'intention
Nous devons nous demander quelle est la fonction de static final
dans notre propre contexte. Voici trois exemples de la manière dont static final
peut être utilisé 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 les majuscules dans les trois scénarios ? Absolument, mais je pense que l'on peut affirmer que cela nuirait à l'objectif de chacun d'entre eux. Examinons donc chaque cas individuellement.
Objet : Variable privée
Dans le cas de la Logger
Dans l'exemple ci-dessus, le logger est déclaré comme privé, et ne sera utilisé que dans la classe, ou éventuellement dans une classe interne. Même s'il était déclaré à protected
o package
visibilité mais son usage est le même :
public void send(final String message) {
logger.info("Sending the following message: '" + message + "'.");
//Send the message
}
Ici, nous n'avons pas soins que logger
est un static final
variable membre. Il peut s'agir simplement d'une final
variable d'instance. Nous ne le savons pas. Nous n'avons pas besoin de savoir. Tout ce que nous devons savoir, c'est que nous enregistrons le message dans le logger que l'instance de la classe a fourni.
public class ChatMessage {
private final Logger logger = LoggerFactory.getLogger(getClass());
}
Vous ne le nommeriez pas LOGGER
dans ce scénario, alors pourquoi le nommer en majuscules si c'était static final
? Son contexte, ou son intention, est le même dans les deux cas.
Note : J'ai inversé ma position sur package
visibilité parce qu'il s'agit plutôt d'une forme de public
accès, limité à package
niveau.
Objet : Enum
Maintenant, vous pourriez dire, pourquoi vous utilisez static final
entiers comme un enum
? C'est un une discussion qui évolue encore et je dirais même semi-controversé, donc je vais essayer de ne pas faire dérailler cette discussion pour longtemps en m'y aventurant. Cependant, il serait suggéré que vous puissiez mettre en œuvre le modèle d'enum 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 d'atteindre le même objectif, à savoir la conversion explicite d'un fichier de type enum->int
y int->enum
. Dans le cadre de la diffusion de ces informations sur un réseau, la sérialisation native de Java est tout simplement trop verbeuse. Un simple int
, short
ou byte
pourrait économiser une énorme bande passante. Je pourrais me lancer dans une longue comparaison et un contraste sur le pour et contre de enum
vs static final int
impliquant la sécurité des types, la lisibilité, la maintenabilité, etc. ; heureusement, cela sort du cadre de cette discussion.
L'essentiel est là, parfois static final int
sera utilisé comme un enum
structure du style .
Si vous pouvez vous résoudre à accepter que la déclaration ci-dessus est vrai Nous pouvons poursuivre avec une discussion sur le style. Lorsque vous déclarez un enum
le style accepté dit que nous ne devons pas faire 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 static final
Le bloc de nombres entiers sert de enum
alors pourquoi utiliser une convention de dénomination différente ? Son contexte, ou son intention, est le même dans les deux cas.
Objet : Propriété statique, constante et publique
Ce cas d'utilisation est peut-être le plus nébuleux et le plus discutable de tous. La constante statique taille L'exemple de l'utilisation est celui où l'on rencontre le plus souvent ce problème. Java supprime la nécessité de sizeof()
mais il arrive qu'il soit 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 que le format de ce fichier binaire exige que la taille totale du fragment de données soit insérée avant les données réelles. Cela est courant pour que le lecteur sache quand les données s'arrêtent, dans le cas où d'autres données sans rapport les suivent. Considérons le format de fichier inventé 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 de MyObject
sérialisés dans un flux d'octets et écrits dans ce fichier. Ce fichier contient 325 octets de MyObject
mais sans connaître la taille de chaque MyObject
vous n'avez aucun moyen de savoir quels octets appartiennent à chaque MyObject
. Ainsi, vous définissez la taille de MyObject
en 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
}
Le site MyObject
occupera 13 octets lorsqu'elle sera écrite dans le fichier comme défini ci-dessus. Sachant cela, lors de la lecture de notre fichier binaire, nous pouvons déterminer de manière dynamique combien de MyObject
les objets suivent dans le dossier :
int dataSize = buffer.getInt();
int totalObjects = dataSize / MyObject.SIZE;
Cela semble être le cas d'utilisation typique et l'argument pour toutes les majuscules. static final
et je suis d'accord pour dire que dans ce contexte, les majuscules ont un sens. Voici pourquoi :
Java n'a pas de struct
comme le langage C, mais une struct
est simplement une classe avec tous les membres publics et sans constructeur. C'est simplement une donnée struct
ure. Ainsi, vous pouvez déclarer un class
sur struct
comme la mode :
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;
}
}
En guise de préambule à cet exemple, je tiens à préciser que, personnellement, je ne procéderais pas à l'analyse syntaxique de cette manière. Je suggérerais plutôt une classe immuable qui gère l'analyse en interne en acceptant une balise ByteBuffer
ou les 4 variables comme arguments du constructeur. Cela dit, l'accès (la définition dans ce cas) de cette 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
Pourtant, il s'agit de membres exposés publiquement qui peuvent être directement définis. Pour cette raison, je pense que lorsqu'un static final
est exposé publiquement, il est logique de le mettre entièrement en majuscules. C'est la seule fois où il est Il est important de la distinguer des variables publiques, non statiques.
Remarque : même dans ce cas, si un développeur tentait de définir un final
ils se heurtent à une erreur de l'IDE ou du compilateur.
Résumé
En conclusion, la convention que vous choisissez pour static final
Les variables vont ê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 :
Méthodologie 1 : évaluer le contexte et l'intention [highly subjective; logical]
- Si c'est un
private
qui ne doit pas être distinguée d'une variable de type private
variable d'instance, puis les nommer de la même façon. tout en minuscules
- Si l'intention est de servir comme un type d'unité libre
enum
bloc de style de static
puis nommez-la comme vous le feriez pour une enum
. casse pascal : paraphe de chaque mot
- Si l'intention est de définir une propriété publiquement accessible, constante et statique, alors laissez-la se démarquer en lui donnant la forme suivante tout en majuscules
Méthodologie 2 : Privé vs. public [objective; logical]
La méthodologie 2 condense essentiellement son contexte en visibilité, et ne laisse aucune place à l'interprétation.
- Si c'est
private
ou protected
alors ce devrait être tout en minuscules .
- Si c'est
public
ou package
alors ce devrait être tout en majuscules .
Conclusion
C'est ainsi que je vois la convention d'appellation de static final
variables. Je ne pense pas qu'il s'agisse de quelque chose qui puisse ou doive être classé dans une catégorie unique. Je pense que vous devriez évaluer son intention avant de décider comment le nommer.
Cependant, l'objectif principal devrait être d'essayer de rester cohérent tout au long de la portée de votre projet/paquet. En fin de compte, c'est tout ce que vous pouvez contrôler.
(Je m'attends à rencontrer de la résistance, mais j'espère aussi obtenir le soutien de la communauté sur cette approche. Quelle que soit votre position, veuillez rester civilisé lorsque vous réprimandez, critiquez ou acclamez ce choix de style).