89 votes

Convention de dénomination Java pour les variables statiques finales

Il y a une règle qui dit :

Les noms représentant des constantes (variables finales) doivent être tout en majuscules. utiliser le trait de soulignement pour séparer les mots (tiré de http://geosoft.no/development/javastyle.html )

qui fonctionne 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 dans les singletons, où la variable d'instance n'est pas en majuscule.

La question est de savoir quelle est la bonne façon de déclarer ces types de variables (comme log et instance) ?

68voto

mre Points 21051

C'est toujours un constant . Voir le JLS pour plus d'informations sur la convention de dénomination des constantes. Mais en réalité, c'est une question de préférence.


Les noms des constantes dans les types d'interface doivent être, et final Les variables des types de classe peuvent être, par convention, une séquence d'une ou de plusieurs variables. mots, d'acronymes ou d'abréviations, tous en majuscules, dont les éléments sont séparés par des traits de soulignement "_" personnages. Les noms des constantes doivent être descriptifs et pas inutilement abrégés. Par convention, ils peuvent être n'importe quelle partie appropriée du discours. Exemples de noms de constantes incluent MIN_VALUE , MAX_VALUE , MIN_RADIX et MAX_RADIX de la classe Character .

Un groupe de constantes qui représentent les valeurs alternatives d'un ensemble, ou, moins fréquemment, des bits de masquage dans une valeur entière, sont parfois sont parfois utilement spécifiés avec un acronyme commun comme préfixe du nom, comme dans :

interface ProcessStates {
  int PS_RUNNING = 0;
  int PS_SUSPENDED = 1;
}

Les obsèques impliquant des noms constants sont rares :

  • Les noms des constantes n'ont normalement pas de lettres minuscules, ils ne masqueront donc pas les noms des paquets ou des types, ni les champs, dont les noms contiennent généralement au moins une lettre minuscule.
  • Les noms de constantes ne peuvent pas masquer les noms de méthodes, car ils sont distingués syntaxiquement.

43voto

crush Points 7891

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).

11voto

Henning Makholm Points 13132

La langue s'en moque. Ce qui est important, c'est de suivre les styles et conventions établis du projet sur lequel vous travaillez, afin que les autres mainteneurs (ou vous dans cinq mois) aient les meilleures chances possibles de ne pas être désorientés.

Je pense qu'un nom tout en majuscules pour un objet mutable m'embrouillerait certainement, même si la référence à cet objet se trouvait être stockée dans un fichier de type static final variable.

7voto

Kashif Nazar Points 921

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 tandis que Logger log est un type non primitif.

Lorsque nous utilisons une constante d'un type primitif, 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 initialisons la constante à un seul endroit private static final Logger log = Logger.getLogger(MyClass.class); nous sommes censés muter ou appeler une méthode sur cette constante ailleurs. log.debug("Problem") . Nous n'aimons pas mettre un opérateur 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 en majuscule. C'est pourquoi LOG.debug("Problem") aurait l'air bizarre.

C'est également le cas pour String types. En général, nous ne sommes pas en train de muter ou d'appeler une méthode sur un String dans notre code et c'est pourquoi nous utilisons la convention d'appellation majuscule pour une constante String objet de type.

4voto

Ernest Friedman-Hill Points 56605

Il n'y a pas de "bonne" manière - il n'y a que des conventions. Vous avez énoncé la convention la plus courante, et celle que je suis dans mon propre code : tous les finales statiques doivent être en majuscules. J'imagine que d'autres équipes suivent d'autres conventions.

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