web-dev-qa-db-ja.com

プライベート最終静的属性とプライベート最終属性

Javaでは、どう違いますか?

private final static int NUMBER = 10;

そして

private final int NUMBER = 10;

どちらもprivatefinalですが、違いはstatic属性です。

何が良いの?なぜ?

277
okami

一般的に、staticは、「タイプのインスタンスではなく、typeに関連付けられている」ことを意味します。

つまり、型のインスタンスを作成することなく静的変数を参照でき、変数を参照するコードはまったく同じデータを参照しています。これをインスタンス変数と比較します。その場合、クラスのインスタンスごとに変数の独立したバージョンが1つあります。たとえば、次のとおりです。

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

10を印刷します。xyは異なるオブジェクトを参照するため、y.instanceVariablex.instanceVariableは別々です。

can参照を介して静的メンバーを参照しますが、そうするのは悪い考えです。行った場合:

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

それは20を出力します-インスタンスごとに1つではなく、1つだけの変数があります。これを次のように書くとより明確になります。

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

これにより、動作がより明確になります。最近のIDEでは、通常、2番目のリストを3番目のリストに変更することをお勧めします。

次のような宣言をする理由はありません

private final int NUMBER = 10;

変更できない場合、インスタンスごとに1つのコピーを作成しても意味がありません。

295
Jon Skeet

finalの場合、初期化時に実行時に異なる値を割り当てることができます。例えば

Class Test{
  public final int a;
}

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

したがって、各インスタンスは異なるフィールド値aを持ちます。

static finalの場合、すべてのインスタンスは同じ値を共有し、最初の初期化後に変更することはできません。

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.
39
lucas

static変数はアプリケーションの存続期間中メモリ内に残り、クラスのロード中に初期化されます。 staticオブジェクトを作成するたびに、非new変数が初期化されます。一般的には使うのが良いです。

private static final int NUMBER = 10;

どうして?これにより、インスタンスあたりのメモリ使用量が削減されます。キャッシュヒットにも有利です。 staticは、特定の型(a.k.a. class)のすべてのインスタンス(別名オブジェクト)で共有されるものに使用するべきです。

26

staticは「クラスに関連付けられている」ことを意味します。それがなければ、変数はクラスの各インスタンスに関連付けられます。静的な場合は、メモリ内に1つしか存在しないことを意味します。そうでない場合は、作成したインスタンスごとに1つずつ存在します。 staticは、クラスがロードされている限り変数がメモリに残ることを意味します。それがなければ、そのインスタンスがであるときに変数をgcすることができます。

16
duffymo

答えを読んで私は実際には要点にたどり着くことができませんでした。これが私の2セントです。

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

}

最初のオブジェクトの結果:

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

2番目のオブジェクトの結果:

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

結論:

私が思ったように、Javaはプリミティブ型と他の型の間に違いを作ります。 Javaのプリミティブ型は常に文字列リテラル(新しいStringオブジェクトではない)と同じように「キャッシュ」されるため、静的メンバーと非静的メンバーの間に違いはありません。

ただし、非静的メンバーがプリミティブ型のインスタンスではない場合、そのメンバーはメモリーが重複します。

Javaが2つのint型変数に同じアドレスを与えるので、valueStaticの値を10に変更するとさらに先へ進みます。

12
StackHola

他の答えでは、一般的に非静的定数を使用する理由はないことを明確にしているように見えますが、定数変数に異なる値を持つさまざまなインスタンスを持つことが可能であることを指摘する人はいませんでした。

次の例を見てください。

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

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

TestClassのインスタンスを3つ作成すると、1つの値のみが生成されて静的定数に格納されるため、同じ乱数値が3回出力されます。

しかし、代わりに次の例を試してみると:

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

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

各インスタンスが独自にランダムに生成された定数値を持っているので、TestClassの3つのインスタンスを作成すると、3つの異なるランダム値が出力されます。

インスタンスごとに異なる定数値を設定することが実際には役立つ状況は考えられませんが、静的ファイナルと非静的ファイナルには明らかな違いがあることを指摘するのに役立ちます。

9
Michiel

これが私の2セントです。

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

例:

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

重要なのは、変数と関数が異なる値を返すことができるということです。そのため、最終的な変数には異なる値を割り当てることができます。

私が行ったテストから、静的最終変数は最終(非静的)変数と同じではありません!最終的な(静的でない)変数はオブジェクトごとに異なります。しかし、それはコンストラクタ内で初期化が行われた場合に限られます。 (コンストラクタから初期化されていない場合は、作成されたすべてのオブジェクトに対して最終的な変数を作成して変更できないため、メモリの浪費にすぎません。)

例えば:

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

    }
}

画面に表示されるものは次のとおりです。

オブジェクトについて:A @ addbf1ファイナル:14静的ファイナル:5

オブジェクトについて:A @ 530daa決勝:21静的決勝:5

匿名1年生IT学生、ギリシャ

2
Anonymous

Jonがすでに述べたように、クラス変数とも呼ばれる静的変数は、クラスのインスタンスにまたがって存在する変数です。

この例 をここに見つけました

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

プログラムの出力は以下のとおりです。

この例でわかるように、各オブジェクトには独自のクラス変数のコピーがあります。

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

Jonの答えに加えて、あなたがstatic finalを使うなら、それは一種の「定義」として振る舞うでしょう。それを使用するクラスをコンパイルすると、それはコンパイル済みの.classファイルに書き込まれます。それについて私のスレッドをチェックしてください ここ

あなたの主な目的のために:あなたがクラスの異なるインスタンスでNUMBERを違ったように使わないのなら、finalとstaticを使うことをお勧めします。 (私のケーススタディで説明されているような問題を考えずに、コンパイルされたクラスファイルをコピーしないことを念頭に置く必要があります。ほとんどの場合これは発生しません。

インスタンスでさまざまな値を使用する方法を説明するには、次のコードを確認してください。

public class JustFinalAttr {
  public final int Number;

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

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

ほんの少し、そして静的

どちらも定数なので、それほど違いはありません。ほとんどのクラスデータオブジェクトにとって、staticはクラス自身に関連するものを意味します。newで作成されたオブジェクトがいくつあっても、コピーは1つだけです。

これは定数なので、実際にはクラスまたはインスタンスのどちらにも格納されていないかもしれませんが、コンパイラーはインスタンスメソッドにアクセスできるようにしていません。リフレクションAPIが存在すると、静的にしないと無意味な作業が必要になる場合もあります。

1
DigitalRoss

クラス内の変数は、同じコマンド内で最後のANDとして初期化されて宣言されているので、インスタンスに関係なく同じ値を持つので、静的変数として宣言しない理由はまったくありません。そのため、すべてのインスタンスが1つの値に対して同じメモリアドレスを共有できるため、各インスタンスに新しい変数を作成する必要がなくなり、1つの共通アドレスを共有することでメモリを節約できます。

1
NarekOnLine

private static finalは定数とみなされ、このクラス内でのみ定数にアクセスできます。キーワードstaticが含まれているので、値はクラスのすべてのオブジェクトに対して一定になります。

プライベート最終変数値は、オブジェクトごとに定数のようになります。

Java.lang.Stringを参照するか、以下の例を探すことができます。

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

//出力:

10
40
20
1
san242

静的変数はクラスに属します(つまり、すべてのオブジェクトがその変数を共有します)。非静的変数は各オブジェクトに属します。

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

上の例からわかるように、 "final int"にはクラスの各インスタンス(オブジェクト)に変数を代入できますが、 "static final int"にはクラスに変数を代入する必要があります(静的変数はクラスに属します) ).

0
Tsasaa

静的、静的最終、最終変数の使用法を理解するためのもう1つの簡単な例です。コードのコメントには正しい説明があります。

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

静的なものは、すべてのクラスインスタンスとクラス自体で同じメンバです。
非静的はすべてのインスタンス(オブジェクト)に対して1つなので、あなたの正確な場合では(= = --- = - )それはあなたがメモリを浪費することになります静的にしない

0
Omar Al-Ithawi

この変数をstaticとマークした場合、ご存知のように、これらの値に再度アクセスするにはstaticメソッドが必要になります。既にstaticメソッドでのみこれらの変数を使用することを考えている場合に役立ちます。もしそうなら、これは最高のものでしょう。

しかし、 "System.out"のように変数を変更することはできないので、変数をパブリックにすることもできます。これもまた、あなたの意図や達成したいことによります。

0
Sanjay

クラスがこれまでに複数のインスタンスを持つことがないのであれば、どのインスタンスがより多くのメモリを消費するのかを考えてみましょう。

private static final int ID = 250;または専用の最終int型ID = 250。

Staticは、メモリ内にコピーが1つしかないクラス型を参照し、staticでないと、インスタンス変数ごとに新しいメモリ位置に配置されることを理解しました。しかし、内部的に同じクラスのインスタンスを1つだけ比較した場合(つまり、複数のインスタンスが作成されない場合)、1つの静的最終変数によって使用されるスペースに関してオーバーヘッドはありますか?

0
rommel

Staticを使用すると、変数の値はすべてのインスタンスを通して同じになります。1つのインスタンスで変更されると、他のインスタンスも変更されます。