web-dev-qa-db-fra.com

#define in Java

Je commence à programmer en Java et je me demande si l’équivalent du C++ #define existe. 

Une recherche rapide sur Google indique que ce n'est pas le cas, mais quelqu'un pourrait-il me dire s'il existe quelque chose de similaire. J'essaie de rendre mon code plus lisible.  

Au lieu de myArray[0], je veux pouvoir écrire myArray[PROTEINS] par exemple.

64
Meir

Non, car il n'y a pas de précompileur.

Cependant, Hotspot est incroyablement bon en optimisation dans la mesure du possible. Dans votre cas, vous pouvez donc obtenir les mêmes résultats.

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

Le compilateur remarquera que PROTEINS ne pourra jamais, jamais changer, et le mettra en ligne, ce qui est plus ou moins ce que vous voulez.

Notez que le modificateur d'accès de la constante n'a pas d'importance ici. Il peut donc s'agir de public ou protected au lieu de privé si vous souhaitez réutiliser la même constante dans plusieurs classes.

87
Andrzej Doyle

Espace de commentaire trop petit, voici quelques informations supplémentaires sur l'utilisation de static final. Comme je l'ai dit dans mon commentaire sur la réponse de Andrzej , seuls les primitives et les String sont compilés directement dans le code en tant que littéraux. Pour illustrer cela, essayez ce qui suit:

Vous pouvez le voir en action en créant trois classes (dans des fichiers séparés):

public class DisplayValue {
    private String value;

    public DisplayValue(String value) {
        this.value = value;
    }

    public String toString() {
        return value;
    }
}

public class Constants {
    public static final int INT_VALUE = 0;
    public static final DisplayValue VALUE = new DisplayValue("A");
}

public class Test {
    public static void main(String[] args) {
        System.out.println("Int   = " + Constants.INT_VALUE);
        System.out.println("Value = " + Constants.VALUE);
    }
}

Compilez-les et lancez Test, qui affiche:

Int    = 0
Value  = A

Maintenant, changez Constants pour avoir une valeur différente pour chacun et ne faites que compiler la classe Constants. Lorsque vous exécutez à nouveau Test (sans recompiler le fichier de classe), l'ancienne valeur est toujours affichée pour INT_VALUE mais pas VALUE. Par exemple:

public class Constants {
    public static final int INT_VALUE = 2;
    public static final DisplayValue VALUE = new DisplayValue("X");
}

Exécuter le test sans recompiler Test.Java:

Int    = 0
Value  = X

Notez que tout autre type utilisé avec static final est conservé comme référence.

Semblable à C/C++ #if/#endif, un littéral constant ou défini par static final avec des primitives, utilisé dans une condition Java if normale et évalué à false fera en sorte que le compilateur supprime le code octet des instructions du bloc if ne pas être généré).

private static final boolean DEBUG = false;

if (DEBUG) {
    ...code here...
}

Le code à "... code ici ..." ne serait pas compilé dans le code d'octet. Mais si vous changiez DEBUG en true, alors ce serait le cas.

37
Kevin Brock
static final int PROTEINS = 1
...
myArray[PROTEINS]

Vous mettriez normalement des "constantes" dans la classe elle-même. Et notez qu’un compilateur est autorisé à optimiser les références, donc ne le changez pas à moins de recompiler toutes les classes qui utilisent.

class Foo {
  public static final int SIZE = 5;

  public static int[] arr = new int[SIZE];
}
class Bar {
  int last = arr[Foo.SIZE - 1]; 
}

Cycle d'édition ... SIZE=4. Compilez également Bar car votre compilateur vient peut-être d'écrire "4" dans le dernier cycle de compilation!

5
extraneon

Java n'a pas de directive de préprocesseur define à usage général.

Dans le cas de constantes, il est recommandé de les déclarer comme static finals, comme dans

private static final int PROTEINS = 100;

De telles déclarations seraient insérées par les compilateurs (si la valeur est une constante de compilation). 

Notez également que les champs de constante finale statiques publics font partie de l'interface publique et que leurs valeurs ne doivent pas changer (car le compilateur les insère). Si vous modifiez la valeur, vous devrez recompiler toutes les sources qui référencent ce champ constant.

4
notnoop

Il y a preprocessor for Java qui fournit des directives telles que #define, #ifdef, #ifndef et beaucoup d'autres, par exemple, l'équipe de PostgresJDBC l'utilise pour générer des sources pour différents cas et pour ne pas dupliquer le code.

3
Igor Maznitsa

La plupart des lisibles} solutions utilisent Importation statique . Ensuite, il vous faudra pas utiliser AnotherClass.constant.

Ecrivez une classe avec la constante comme champ public static

package ConstantPackage;

public class Constant {
    public static int PROTEINS = 1;
}

Ensuite, utilisez simplement Importation statique où vous avez besoin de la constante.

import static ConstantPackage.Constant.PROTEINS;

public class StaticImportDemo {

    public static void main(String[]args) {

        int[] myArray = new int[5];
        myArray[PROTEINS] = 0;

    }
}

Pour en savoir plus sur l'importation statique, veuillez consulter cette question de débordement de pile .

La réponse la plus simple est "Aucune méthode directe pour l'obtenir car il n'y a pas de pré-compilateur" Mais vous pouvez le faire vous-même. Utilisez les classes puis définissez les variables comme final afin qu'il puisse être supposé constant tout au long du programme
N'oubliez pas d'utiliser final et variable comme public ou protégé et non privé, sinon vous ne pourrez pas y accéder depuis l'extérieur de cette classe. 

0
Jitendra Nagar

Java Primitive Specializations Generator supporte les blocs /* with */, /* define */ et /* if */ ... /* Elif */ ... /* endif */ qui permettent de générer une sorte de macro en code Java, similaire au préprocesseur Java-comment mentionné dans cette réponse .

JPSG a des plugins Maven et Gradle.

0
leventov