web-dev-qa-db-fra.com

attribut statique final final 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 final, la différence est l'attribut static.

Ce qui est mieux? Et pourquoi?

269
okami

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

Cela signifie que vous pouvez référencer une variable statique sans avoir jamais créé d'instances du type, et tout code faisant référence à la variable fait référence aux mêmes données. Comparez cela avec une variable d'instance: dans ce cas, il existe 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);

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

Vous pouvez faites référence à des membres statiques via des références, bien que ce soit une mauvaise idée de le faire. Si nous l'avons fait:

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

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

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 cela ne peut pas changer, il ne sert à rien d'avoir une copie par instance.

285
Jon Skeet

Pour final , différentes valeurs peuvent être affectées 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 de champ a .

Pour static final , toutes les instances partagent la même valeur et ne peuvent pas être modifiées après la première initialisation. 

Class TestStatic{
      public static final int a;
}

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

Une variable static reste en mémoire pendant toute la durée de vie de l'application et est initialisée pendant le chargement de la classe. Une variable non -static est en cours d'initialisation chaque fois que vous construisez un objet new. Il est généralement préférable d'utiliser:

private static final int NUMBER = 10;

Pourquoi? Cela réduit l'encombrement de la mémoire par instance. C'est peut-être aussi favorable pour les hits de cache. Et cela a du sens: static devrait être utilisé pour les éléments partagés entre toutes les instances (objets a.k.a.) d’un certain type (a.k.a. class).

25
Martijn Courteaux

statique signifie "associé à la classe"; sans elle, la variable est associée à chaque instance de la classe. Si c'est statique, cela signifie que vous n'en aurez qu'un en mémoire; sinon, vous en aurez un pour chaque instance que vous créez. static signifie que la variable restera en mémoire aussi longtemps que la classe sera chargée; sans elle, la variable peut être gc'd quand son instance est.

16
duffymo

En lisant les réponses, je n'ai trouvé aucun test qui soit vraiment pertinent. Voici mes 2 centimes:

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 la différence entre les types primitifs et autres. Les types primitifs en Java sont toujours "mis en cache", comme pour les littéraux de chaînes (pas les nouveaux objets String), donc pas de différence entre les membres statiques et non statiques.

Cependant, il existe une duplication de mémoire pour les membres non statiques s'ils ne sont pas une instance de type primitif.

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

12
StackHola

Alors que les autres réponses semblent indiquer assez clairement qu'il n'y a généralement aucune raison d'utiliser des constantes non statiques, je n'ai trouvé personne qui indique qu'il est possible d'avoir différentes instances avec des valeurs différentes sur leurs variables constantes.

Prenons l'exemple suivant:

public class TestClass {
    private final static double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

La création de trois instances de TestClass imprimerait la même valeur aléatoire trois fois, car une seule valeur est générée et stockée dans la constante statique.

Cependant, lorsque vous essayez plutôt l'exemple suivant:

public class TestClass {
    private final double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

La création de trois instances de TestClass afficherait maintenant trois valeurs aléatoires différentes, car chaque instance possède sa propre valeur constante générée de manière aléatoire.

Je ne peux penser à aucune situation où il serait vraiment utile d’avoir différentes valeurs constantes sur différentes instances, mais j’espère que cela aide à souligner qu’il existe une nette différence entre les finales statiques et non statiques.

9
Michiel

Voici mes deux cents:

final           String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
final   static  String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";

Exemple:

package test;

public class Test {

    final long OBJECT_ID = new Random().nextLong();
    final static long CLASSS_ID = new Random().nextLong();

    public static void main(String[] args) {
        Test[] test = new Test[5];
        for (int i = 0; i < test.length; i++){
            test[i] = new Test();
            System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value
            System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different
        }
    }
}

La clé est que les variables et les fonctions peuvent renvoyer des valeurs différentes. Par conséquent, les variables finales peuvent être affectées avec des valeurs différentes.

2

D'après les tests que j'ai effectués, les variables finales statiques ne sont pas identiques aux variables finales (non statiques)! Les variables finales (non statiques) peuvent différer d'un objet à l'autre !!! Mais ce n'est que si l'initialisation est faite dans le constructeur! (S'il n'est pas initialisé à partir du constructeur, il ne s'agit que d'un gaspillage de mémoire car il crée des variables finales pour chaque objet créé qui ne peut pas être modifié.)

Par exemple:

class A
{
    final int f;
    static final int sf = 5;

    A(int num)
    {
        this.f = num;
    }

    void show()
    {
        System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf);
    }

    public static void main(String[] args)
    {
        A ob1 = new A(14);
        ob1.show();

        A ob2 = new A(21);
        ob2.show();

    }
}

Ce qui apparaît à l'écran est:

A propos de l'objet: A@addbf1 Finale: 14 Finale statique: 5

À propos de l'objet: A@530daa Finale: 21 Finale statique: 5

Anonyme étudiant en informatique, Grèce

2
Anonymous

Comme déjà dit Jon, une variable statique, également appelée variable de classe, est une variable qui existe entre les instances d'une classe.

J'ai trouvé un exemple de ceci ici :

public class StaticVariable
{
  static int noOfInstances;
  StaticVariable()
  {
    noOfInstances++;
  }
  public static void main(String[] args)
  {
    StaticVariable sv1 = new StaticVariable();
    System.out.println("No. of instances for sv1 : " + sv1.noOfInstances);

    StaticVariable sv2 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for st2 : "  + sv2.noOfInstances);

    StaticVariable sv3 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for sv2 : "  + sv2.noOfInstances);
    System.out.println("No. of instances for sv3 : "  + sv3.noOfInstances);
  }
}

Le résultat du programme est donné ci-dessous:

Comme nous pouvons le voir dans cet exemple, chaque objet a sa propre copie de variable de classe.

C:\Java>Java StaticVariable
No. of instances for sv1 : 1
No. of instances for sv1 : 2
No. of instances for st2 : 2
No. of instances for sv1 : 3
No. of instances for sv2 : 3
No. of instances for sv3 : 3
2
Novitzky

En outre, à la réponse de Jon, si vous utilisez statique final, il se comportera comme une sorte de "définition". Une fois que vous compilez la classe qui l'utilise, il sera dans le fichier compilé .class burnt . Consultez mon fil à ce sujet ici .

Pour votre objectif principal: si vous n'utilisez pas NUMBER différemment dans les différentes instances de la classe, je vous conseillerais d'utiliser final et static .(vous devez simplement garder à l'esprit de ne pas copier les fichiers de classe compilés sans prendre en compte les problèmes éventuels tels que ceux décrits dans mon étude de cas. La plupart des cas ne se produisent pas, ne vous inquiétez pas :))

Pour vous montrer comment utiliser différentes valeurs dans les instances, vérifiez ce code:

public class JustFinalAttr {
  public final int Number;

  public JustFinalAttr(int a){
    Number=a;
  }
}

...System.out.println(new JustFinalAttr(4).Number);
2
BlondCode

très peu et statique

Il n'y a pas beaucoup de différence car ce sont les deux constantes. Pour la plupart des objets de données de classe, le terme statique signifie quelque chose associé à la classe elle-même: il n’existe qu’une seule copie, quel que soit le nombre d’objets créés avec new.

Comme il s'agit d'une constante, il est possible qu'elle ne soit réellement stockée ni dans la classe ni dans une instance, mais le compilateur ne vous laissera toujours pas accéder aux objets d'instance à partir d'une méthode statique, même s'il sait ce qu'ils seraient. L'existence de l'API de réflexion peut également nécessiter un travail inutile si vous ne la rendez pas statique.

1
DigitalRoss

Puisqu'une variable dans une classe est déclarée comme finale ET initialisée dans la même commande, Il n'y a absolument aucune raison de ne pas la déclarer comme statique, car elle aura la même valeur, peu importe l'instance. Ainsi, toutes les instances peuvent partager la même adresse mémoire pour une valeur, ce qui permet de gagner du temps de traitement en éliminant le besoin de créer une nouvelle variable pour chaque instance et d'économiser de la mémoire en partageant une adresse commune.

1
NarekOnLine

private statique final sera considéré comme constant et la constante est accessible uniquement dans cette classe. Depuis, le mot-clé static inclus, la valeur sera constante pour tous les objets de la classe.

la valeur de la variable finale privée sera comme constante par objet.

Vous pouvez vous référer à Java.lang.String ou rechercher l'exemple ci-dessous.

public final class Foo
{

    private final int i;
    private static final int j=20;

    public Foo(int val){
        this.i=val;
    }

    public static void main(String[] args) {
        Foo foo1= new Foo(10);

        Foo foo2= new Foo(40);

        System.out.println(foo1.i);
        System.out.println(foo2.i);
        System.out.println(check.j);
    }
}

//Sortie:

10
40
20
1
san242

La variable statique appartient à la classe (ce qui signifie que tous les objets partagent cette variable). La variable non statique appartient à chaque objet.

public class ExperimentFinal {

private final int a;
private static final int b = 999; 

public ExperimentFinal(int a) {
    super();
    this.a = a;
}
public int getA() {
    return a;
}
public int getB() {
    return b;
}
public void print(int a, int b) {
    System.out.println("final int: " + a + " \nstatic final int: " + b);
}
public static void main(String[] args) {
    ExperimentFinal test = new ExperimentFinal(9);
    test.print(test.getA(), test.getB());
} }

Comme vous pouvez le voir ci-dessus, pour "final int", nous pouvons affecter notre variable à chaque instance (objet) de la classe. Toutefois, pour "static final int", nous devons affecter une variable à la classe (la variable statique appartient à la classe. ).

0
Tsasaa

Juste un autre exemple simple pour comprendre l’utilisation des variables statiques, finales, finales. Les commentaires de code ont l'explication appropriée.

public class City {

    // base price that is always same for all objects[For all cities].
    private static double iphone_base_price = 10000;

    // this is total price = iphone_base_price+iphone_diff;
    private double iphone_citi_price;

    // extra price added to iphone_base_price. It is constant per city. Every
    // city has its own difference defined,
    private final double iphone_diff;

    private String cityName = "";

    // static final will be accessible everywhere within the class but cant be
    // changed once initialized.
    private static final String countryName = "India";

    public City(String cityName, double iphone_diff) {
        super();
        this.iphone_diff = iphone_diff;
        iphone_citi_price = iphone_base_price + iphone_diff;
        this.cityName = cityName;

    }

    /**
     * get phone price
     * 
     * @return
     */
    private double getPrice() {

        return iphone_citi_price;
    }

    /**
     * Get city name
     * 
     * @return
     */
    private String getCityName() {

        return cityName;
    }

    public static void main(String[] args) {

        // 300 is the
        City newyork = new City("Newyork", 300);
        System.out.println(newyork.getPrice() + "  " + newyork.getCityName());

        City california = new City("California", 800);
        System.out.println(california.getPrice() + "  " + california.getCityName());

        // We cant write below statement as a final variable can not be
        // reassigned
        // california.iphone_diff=1000; //************************

        // base price is defined for a class and not per instances.
        // For any number of object creation, static variable's value would be the same
        // for all instances until and unless changed.
        // Also it is accessible anywhere inside a class.
        iphone_base_price = 9000;

        City delhi = new City("delhi", 400);
        System.out.println(delhi.getPrice() + "  " + delhi.getCityName());

        City moscow = new City("delhi", 500);
        System.out.println(moscow.getPrice() + "  " + moscow.getCityName());

        // Here countryName is accessible as it is static but we can not change it as it is final as well. 
        //Something are meant to be accessible with no permission to modify it. 
        //Try un-commenting below statements
        System.out.println(countryName);

        // countryName="INDIA";
        // System.out.println(countryName);

    }

}
0
Vaibs

Le membre statique est le même membre sur toutes les instances de la classe et la classe elle-même.
Le non-statique est un pour chaque instance (objet), donc dans votre cas exact c'est un gaspillage de mémoire si vous ne le faites pas mettez statique.

0
Omar Al-Ithawi

Si vous marquez cette variable comme statique, comme vous le savez, vous auriez besoin de méthodes statiques pour accéder à nouveau à ces valeurs. Cela sera utile si vous envisagez déjà d'utiliser ces variables uniquement dans des méthodes statiques. Si tel est le cas, ce serait le meilleur.

Vous pouvez cependant rendre la variable maintenant publique puisque personne ne peut la modifier de la même manière que "System.out", cela dépend à nouveau de vos intentions et de ce que vous voulez atteindre.

0
Sanjay

Disons que si la classe n'aura jamais plus d'une instance, laquelle prend plus de mémoire:

privé statique final int ID = 250; ou privé final ID: 250;

J'ai compris que statique ferait référence au type de classe avec une seule copie dans la mémoire et non statique serait dans un nouvel emplacement mémoire pour chaque variable d'instance. Cependant, en interne, si nous ne comparons qu'une seule instance de la même classe (c.-à-d. Plus d'une instance ne serait pas créée), existe-t-il une surcharge en termes d'espace utilisé par une variable finale statique?

0
rommel

Si vous utilisez static, la valeur de la variable sera la même dans toutes vos instances, mais si elle est modifiée dans une instance, les autres changeront également.