336 votes

attribut statique final privé vs attribut final privé

En java, quelle est la différence entre :

private final static int NUMBER = 10;

Et

private final int NUMBER = 10;

Les deux sont private et les deux sont final la différence est que static attribut.

Qu'est-ce qui est le mieux à utiliser ? Et pourquoi ?

331voto

Jon Skeet Points 692016

En général, static signifie "associé à la type lui-même, plutôt qu'un instance du type."

Cela signifie que vous pouvez faire référence à une variable statique sans avoir jamais créé d'instances du type, et que tout code faisant référence à la variable se réfère exactement aux mêmes données. Comparez cela avec une variable d'instance : dans ce cas, il y a une version indépendante de la variable par instance de la classe. Donc, par exemple :

Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);

imprime 10 : y.instanceVariable et x.instanceVariable sont séparés, car x et y font référence à des objets différents.

Vous peut faire référence à des membres statiques via des références, bien que ce soit une mauvaise idée de le faire. Si nous le faisions :

Test x = new Test();
Test y = new Test();
x.staticVariable = 10;
y.staticVariable = 20;
System.out.println(x.staticVariable);

alors cela donnerait 20 - il n'y a qu'une seule variable, pas une par instance. Il aurait été plus clair d'écrire ceci comme :

Test x = new Test();
Test y = new Test();
Test.staticVariable = 10;
Test.staticVariable = 20;
System.out.println(Test.staticVariable);

Cela rend le comportement beaucoup plus évident. Les IDE modernes suggèrent généralement de remplacer la deuxième liste par la troisième.

Il n'y a aucune raison d'avoir une déclaration telle que

private final int NUMBER = 10;

Si elle ne peut pas changer, il est inutile d'avoir une copie par instance.

46voto

Martijn Courteaux Points 33836

Une variable statique reste dans la mémoire. Une variable non statique est initialisée à chaque fois que vous appelez le constructeur. Je pense qu'il est préférable d'utiliser

private static final int NUMBER = 10;

36voto

lucas Points 1011

Pour final il est possible de lui attribuer différentes valeurs au moment de l'exécution, lors de l'initialisation. Par exemple

Class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

Ainsi, chaque instance a une valeur différente du champ a .

Pour statique final toutes les instances partagent la même valeur, et ne peuvent pas être modifiées après avoir été initialisées.

Class TestStatic{
      public static final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.

17voto

duffymo Points 188155

Static signifie "associé à la classe" ; sans cela, la variable est associée à chaque instance de la classe. Si elle est statique, cela signifie que vous n'en aurez qu'une seule en mémoire ; sinon, vous en aurez une pour chaque instance créée. static signifie que la variable restera en mémoire tant que la classe sera chargée ; sans cela, la variable peut être gc'd lorsque son instance l'est.

13voto

Michael.P Points 326

En lisant les réponses, je n'ai trouvé aucun test qui aille vraiment droit au but. Voici mes deux cents :

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {

        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " + 
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " + 
                ObjectUtils.identityToString(valueObjectStatic));
    }

    public static void main(final String args[]) {

        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

Résultats pour le premier objet :

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@6c22c95b
final static file address java.io.File@5fd1acd3

Résultats pour le 2ème objet :

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@3ea981ca
final static file address java.io.File@5fd1acd3

Conclusion :

Comme je le pensais, Java fait une différence entre les types primitifs et les autres types. Les types primitifs en Java sont toujours "mis en cache", de même pour les chaînes littérales (pas les nouveaux objets String), donc aucune différence entre les membres statiques et non statiques.

Cependant, il y a une duplication de la mémoire pour les membres non statiques s'ils ne sont pas des instances d'un type primitif.

Changer la valeur de valueStatic en 10 ira même plus loin car Java donnera les mêmes adresses aux deux variables int.

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