it-swarm.com.de

privates endgültiges statisches Attribut vs. privates endgültiges Attribut

Was ist in Java der Unterschied zwischen:

private final static int NUMBER = 10;

und

private final int NUMBER = 10;

Beide sind private und final, der Unterschied ist das static-Attribut.

Was ist besser? Und warum?

269
okami

Im Allgemeinen bedeutet static "dem Typ selbst zugeordnet, anstatt einem Instanz des Typs."

Das heißt, Sie können auf eine statische Variable verweisen, ohne jemals Instanzen des Typs erstellt zu haben, und jeder Code, der sich auf die Variable bezieht, bezieht sich auf genau dieselben Daten. Vergleichen Sie dies mit einer Instanzvariablen: In diesem Fall gibt es eine unabhängige Version der Variablen pro Instanz der Klasse. Also zum Beispiel:

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

druckt 10 aus: y.instanceVariable und x.instanceVariable sind getrennt, da x und y sich auf verschiedene Objekte beziehen.

Sie können über Referenzen auf statische Mitglieder verweisen, obwohl dies keine gute Idee ist. Wenn wir das getan hätten:

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

dann würde das 20 ausgeben - es gibt nur eine Variable, nicht eine pro Instanz. Es wäre klarer gewesen, dies so zu schreiben:

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

Das macht das Verhalten viel offensichtlicher. Moderne IDEs schlagen normalerweise vor, die zweite Auflistung in die dritte zu ändern.

Es gibt keinen Grund für eine Erklärung wie

private final int NUMBER = 10;

Wenn es sich nicht ändern kann, gibt es keinen Grund, eine Kopie pro Instanz zu haben.

295
Jon Skeet

Für final können bei der Initialisierung unterschiedliche Werte zur Laufzeit zugewiesen werden. Zum Beispiel

Class Test{
  public final int a;
}

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

Somit hat jede Instanz einen anderen Wert für Feld a .

Bei static final haben alle Instanzen denselben Wert und können nach der ersten Initialisierung nicht geändert werden. 

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

Eine Variable static bleibt während der gesamten Lebensdauer der Anwendung im Speicher und wird beim Laden der Klasse initialisiert. Jedes Mal, wenn Sie ein static -Objekt erstellen, wird eine Nicht-new-Variable initialisiert. Im Allgemeinen ist es besser zu verwenden:

private static final int NUMBER = 10;

Warum? Dies reduziert den Speicherbedarf pro Instanz. Möglicherweise ist es auch günstig für Cache-Treffer. Und es macht einfach Sinn: static sollte für Dinge verwendet werden, die von allen Instanzen (a.k.a.-Objekten) eines bestimmten Typs (a.k.a. class) gemeinsam genutzt werden.

25

statisch bedeutet "der Klasse zugeordnet"; Andernfalls wird die Variable jeder Instanz der Klasse zugeordnet. Wenn es statisch ist, bedeutet dies, dass Sie nur einen im Speicher haben. Andernfalls haben Sie für jede von Ihnen erstellte Instanz eine. statisch bedeutet, dass die Variable so lange im Speicher bleibt, wie die Klasse geladen ist; Ohne sie kann die Variable gc werden, wenn ihre Instanz ist.

16
duffymo

Beim Lesen der Antworten fand ich keinen echten Test, der wirklich auf den Punkt kam. Hier sind meine 2 Cent:

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();
    }

}

Ergebnisse für erstes Objekt:

final int address [email protected]
final static int address [email protected]
final file address [email protected]
final static file address [email protected]

Ergebnisse für das 2. Objekt:

final int address [email protected]
final static int address [email protected]
final file address [email protected]
final static file address [email protected]

Fazit :

Wie ich dachte, macht Java einen Unterschied zwischen primitiven und anderen Typen. Grundlagentypen in Java werden immer "zwischengespeichert". Dies gilt auch für Zeichenfolgenliterale (nicht neue String-Objekte), sodass zwischen statischen und nicht statischen Elementen kein Unterschied besteht.

Es gibt jedoch eine Speicherduplikation für nicht statische Member, wenn diese keine Instanz eines primitiven Typs sind.

Das Ändern des Werts von valueStatic auf 10 wird sogar noch weiter gehen, da Java den beiden int-Variablen die gleichen Adressen zuweist.

12
StackHola

Während die anderen Antworten offenbar deutlich machen, dass es im Allgemeinen keinen Grund gibt, nicht statische Konstanten zu verwenden, konnte ich niemanden finden, der darauf hinweist, dass es möglich ist, verschiedene Instanzen mit unterschiedlichen Werten für ihre konstanten Variablen zu haben.

Betrachten Sie das folgende Beispiel:

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

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

Bei der Erstellung von drei Instanzen von TestClass würde derselbe Zufallswert dreimal gedruckt, da nur ein Wert generiert und in der statischen Konstante gespeichert wird.

Versuchen Sie jedoch stattdessen das folgende Beispiel:

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

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

Beim Erstellen von drei TestClass-Instanzen werden jetzt drei verschiedene Zufallswerte gedruckt, da jede Instanz einen eigenen zufällig generierten konstanten Wert hat.

Ich kann mir keine Situation vorstellen, in der es sehr nützlich wäre, unterschiedliche konstante Werte für verschiedene Instanzen zu haben, aber ich hoffe, dass dies den Unterschied zwischen statischen und nicht statischen Finals hervorhebt.

9
Michiel

Hier sind meine zwei Cents:

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

Beispiel:

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
        }
    }
}

Der Schlüssel ist, dass Variablen und Funktionen unterschiedliche Werte zurückgeben können. Daher können Endvariablen unterschiedliche Werte zugewiesen werden.

Bei den von mir durchgeführten Tests stimmen die statischen Endvariablen nicht mit den endgültigen (nicht statischen) Variablen überein! Endgültige (nicht statische) Variablen können sich von Objekt zu Objekt unterscheiden !!! Das ist aber nur dann der Fall, wenn die Initialisierung innerhalb des Konstruktors erfolgt! (Wenn es nicht vom Konstruktor aus initialisiert wird, ist dies nur eine Verschwendung von Speicher, da für jedes erstellte Objekt endgültige Variablen erstellt werden, die nicht geändert werden können.)

Zum Beispiel:

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();

    }
}

Was auf dem Bildschirm angezeigt wird, ist:

Über Objekt: [email protected] Finale: 14 Statisches Finale: 5

Über Objekt: [email protected] Finale: 21 Statisches Finale: 5

Anonymer IT-Student im ersten Jahr, Griechenland

2
Anonymous

Wie bereits gesagt, ist eine statische Variable, auch als Klassenvariable bezeichnet, eine Variable, die über Instanzen einer Klasse hinweg existiert.

Ich habe ein Beispiel dafür gefunden hier :

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);
  }
}

Die Ausgabe des Programms ist unten angegeben:

Wie wir in diesem Beispiel sehen können, hat jedes Objekt eine eigene Kopie der Klassenvariablen.

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

Außerdem verhält sich Jons Antwort, wenn Sie static final verwenden, wie eine Art "Definition". Sobald Sie die Klasse kompiliert haben, die sie verwendet, wird sie in der kompilierten .class-Datei gebrannt. Überprüfen Sie meinen Thread darüber hier .

Für Ihr Hauptziel: Wenn Sie die NUMBER in den verschiedenen Instanzen der Klasse nicht unterschiedlich verwenden, würde ich empfehlen, final und static zu verwenden. (Denken Sie nur daran, kompilierte Klassendateien nicht zu kopieren, ohne mögliche Probleme zu berücksichtigen, wie sie in meiner Fallstudie beschrieben werden. In den meisten Fällen tritt dies nicht auf. Machen Sie sich keine Sorgen: ))

Um Ihnen zu zeigen, wie Sie verschiedene Werte in Instanzen verwenden können, überprüfen Sie diesen Code:

public class JustFinalAttr {
  public final int Number;

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

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

sehr wenig und statisch

Es gibt keinen großen Unterschied, da beide Konstanten sind. Für die meisten Klassendatenobjekte bedeutet statisch etwas, das der Klasse selbst zugeordnet ist. Es gibt nur eine Kopie, unabhängig davon, wie viele Objekte mit neuen Objekten erstellt wurden.

Da es sich um eine Konstante handelt, wird sie möglicherweise weder in der Klasse noch in einer Instanz gespeichert. Der Compiler lässt Sie jedoch immer noch nicht mit einer statischen Methode auf Instanzobjekte zugreifen, selbst wenn er weiß, was sie sind. Das Vorhandensein der Reflection-API kann auch einige sinnlose Arbeit erfordern, wenn Sie sie nicht statisch machen.

1
DigitalRoss

Da eine Variable in einer Klasse im selben Befehl als final UND initialisiert wird, gibt es absolut keinen Grund, sie nicht als statisch zu deklarieren, da sie unabhängig von der Instanz denselben Wert hat. Daher können alle Instanzen dieselbe Speicheradresse für einen Wert verwenden, wodurch sich Verarbeitungszeit einspart, da keine neue Variable für jede Instanz erstellt werden muss und durch die gemeinsame Nutzung einer gemeinsamen Adresse Speicher eingespart werden muss.

1
NarekOnLine

private static final wird als konstant betrachtet und die Konstante kann nur innerhalb dieser Klasse abgerufen werden. Da das Schlüsselwort static eingeschlossen ist, ist der Wert für alle Objekte der Klasse konstant.

der Wert der privaten abschließenden Variablen ist wie ein konstantes Objekt.

Sie können auf den Java.lang.String verweisen oder nach dem folgenden Beispiel suchen.

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);
    }
}

//Ausgabe:

10
40
20
1
san242

Die statische Variable gehört zur Klasse (dh alle Objekte teilen sich diese Variable). Nicht statische Variablen gehören zu jedem Objekt.

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());
} }

Wie Sie oben sehen können, können wir für "final int" unsere Variable für jede Instanz (Objekt) der Klasse zuweisen, für "static final int" sollten wir jedoch eine Variable in der Klasse zuweisen (statische Variable gehört zur Klasse.) ).

0
Tsasaa

Ein weiteres einfaches Beispiel, um die Verwendung statischer, statischer finaler und finaler Variablen zu verstehen. Code-Kommentare haben die richtige Erklärung.

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

Das statische Element ist in allen Klasseninstanzen und in der Klasse selbst das gleiche Mitglied.
Das Nicht-Statische ist eines für jede Instanz (Objekt), also in Ihrem genauen Fall ist es eine Verschwendung von Speicher, wenn Sie nicht statisch setzen.

0
Omar Al-Ithawi

Wenn Sie diese Variable als statisch markieren, benötigen Sie, wie Sie wissen, statische Methoden, um wieder auf diese Werte zuzugreifen. Dies ist hilfreich, wenn Sie bereits daran denken, diese Variablen nur in statischen Methoden zu verwenden. Wenn dies so ist, wäre dies das beste.

Sie können die Variable jedoch jetzt als öffentlich definieren, da sie nicht wie "System.out" geändert werden kann. Sie hängt wiederum von Ihren Absichten ab und davon, was Sie erreichen möchten.

0
Sanjay

Lass uns sagen, wenn die Klasse nie mehr als eine Instanz haben wird, dann braucht man mehr Speicherplatz:

private statische endgültige int ID = 250; oder private endgültige int ID = 250;

Ich habe verstanden, dass sich statisch auf den Klassentyp bezieht, wobei sich nur eine Kopie im Speicher befindet und sich nicht statisch an einer neuen Speicherposition für jede Instanzvariable befindet. Wenn wir jedoch intern nur eine Instanz derselben Klasse vergleichen (d. H., Würde mehr als eine Instanz nicht erstellt), gibt es dann einen zusätzlichen Platzbedarf in Bezug auf den Speicherplatz, der von einer statischen finalen Variablen verwendet wird.

0
rommel

Wenn Sie statisch verwenden, ist der Wert der Variablen für alle Ihre Instanzen gleich. Wenn Sie in einer Instanz geändert werden, ändern sich auch die anderen.