Java では、次の違いは何ですか。
private final static int NUMBER = 10;
と
private final int NUMBER = 10;
どちらもprivate
とfinal
で、違いはstatic
属性です。
何が良いですか?なぜ?
Java では、次の違いは何ですか。
private final static int NUMBER = 10;
と
private final int NUMBER = 10;
どちらもprivate
とfinal
で、違いはstatic
属性です。
何が良いですか?なぜ?
一般に、 「型のインスタンスではなく、型static
自体に関連付けられている」ことを意味します。
つまり、型のインスタンスを作成しなくても静的変数を参照でき、変数を参照するコードはまったく同じデータを参照しています。これをインスタンス変数と比較してください。その場合、クラスのインスタンスごとに変数の独立したバージョンが 1 つあります。たとえば、次のようになります。
Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);
と は別のオブジェクトを参照しているため、 10:y.instanceVariable
とx.instanceVariable
は別個に出力されます。x
y
参照を介して静的メンバーを参照することはできますが、そうするのは悪い考えです。もしそうなら:
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 番目に変更することを提案します。
次のようにインライン宣言で値を初期化する理由はありません。各インスタンスには独自の値がありますNUMBER
が、常に同じ値 (不変であり、リテラルで初期化されます) を持つためです。これは、final static
すべてのインスタンスに対して変数を 1 つだけ持つことと同じです。
private final int NUMBER = 10;
したがって、変更できない場合は、インスタンスごとに 1 つのコピーを持つ意味がありません。
ただし、次のようなコンストラクターで初期化されている場合は理にかなっています。
// No initialization when is declared
private final int number;
public MyClass(int n) {
// The variable can be assigned in the constructor, but then
// not modified later.
number = n;
}
これで、 のインスタンスごとにMyClass
、 の異なるが不変の値を持つことができますnumber
。
変数は、アプリケーションのstatic
存続期間全体にわたってメモリ内にとどまり、クラスのロード中に初期化されます。static
オブジェクトを構築するたびに、非変数が初期化されていnew
ます。一般的には、次を使用することをお勧めします。
private static final int NUMBER = 10;
なんで?これにより、インスタンスごとのメモリ フットプリントが削減されます。キャッシュ ヒットにも有利な場合があります。そして、それは理にかなっています:static
特定のタイプ (別名 ) のすべてのインスタンス (別名オブジェクト) で共有されるものに使用する必要がありますclass
。
static は「クラスに関連付けられている」ことを意味します。それがない場合、変数はクラスの各インスタンスに関連付けられます。静的な場合は、メモリに 1 つしかないことを意味します。そうでない場合は、作成するインスタンスごとに 1 つになります。static は、クラスがロードされている限り、変数がメモリに残ることを意味します。それがなければ、インスタンスがそうであるときに変数を gc することができます。
答えを読んで、実際のテストが本当に要点に達していないことがわかりました。これが私の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 オブジェクトではない) と同じであるため、静的メンバーと非静的メンバーに違いはありません。
ただし、非静的メンバーがプリミティブ型のインスタンスでない場合、メモリの重複があります。
valueStatic の値を 10 に変更すると、Java が 2 つの int 変数に同じアドレスを与えるため、さらに先に進みます。
他の答えは、一般的に非静的定数を使用する理由がないことをかなり明確にしているように見えますが、定数変数に異なる値を持つさまざまなインスタンスを持つことが可能であることを指摘する人を見つけることができませんでした。
次の例を検討してください。
public class TestClass {
private final static double NUMBER = Math.random();
public TestClass () {
System.out.println(NUMBER);
}
}
TestClass の 3 つのインスタンスを作成すると、同じランダム値が 3 回出力されます。これは、値が 1 つだけ生成されて静的定数に格納されるためです。
ただし、代わりに次の例を試すと:
public class TestClass {
private final double NUMBER = Math.random();
public TestClass () {
System.out.println(NUMBER);
}
}
TestClass の 3 つのインスタンスを作成すると、3 つの異なるランダム値が出力されます。これは、各インスタンスがランダムに生成された独自の定数値を持っているためです。
異なるインスタンスで異なる定数値を持つことが実際に役立つ状況は考えられませんが、これが静的と非静的のファイナルの間に明確な違いがあることを指摘するのに役立つことを願っています.
私が行ったテストから、静的最終変数は最終(非静的)変数と同じではありません! 最終 (非静的) 変数は、オブジェクトごとに異なる場合があります!!! ただし、それはコンストラクター内で初期化が行われた場合のみです! (コンストラクターから初期化されていない場合は、変更できない作成されたすべてのオブジェクトの最終変数を作成するため、メモリの無駄になります。)
例えば:
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 Final: 14 Static Final: 5
オブジェクトについて: A@530daa ファイナル: 21 スタティック ファイナル: 5
Anonymous 1 年生 IT 学生、ギリシャ
どちらも定数であるため、大きな違いはありません。ほとんどのクラス データ オブジェクトでは、static はクラス自体に関連付けられたものを意味し、new で作成されたオブジェクトの数に関係なく、コピーは 1 つだけです。
これは定数であるため、実際にはクラスにもインスタンスにも格納されていない可能性がありますが、コンパイラは、インスタンス オブジェクトが何であるかを知っていても、静的メソッドからインスタンス オブジェクトにアクセスすることはできません。リフレクション API の存在は、静的にしないと無意味な作業が必要になる場合もあります。
すでにジョンが言ったように、クラス変数とも呼ばれる静的変数は、クラスのインスタンス全体に存在する変数です。
ここでこの例を見つけました:
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セントがあります:
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
}
}
}
重要なのは、変数と関数が異なる値を返すことができるということです。したがって、最終的な変数には異なる値を割り当てることができます。
クラス内の変数は final として宣言され、同じコマンドで初期化されるため、インスタンスに関係なく同じ値を持つため、静的として宣言しない理由はまったくありません。そのため、すべてのインスタンスが値に対して同じメモリ アドレスを共有できるため、インスタンスごとに新しい変数を作成する必要がなくなり、1 つの共通アドレスを共有することでメモリを節約できるため、処理時間が節約されます。
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つであるため、正確な場合、静的にしないとメモリの浪費になります。
この変数を static とマークすると、ご存知のように、これらの値に再度アクセスするために静的メソッドが必要になります。これは、これらの変数を静的メソッドでのみ使用することを既に考えている場合に役立ちます。もしそうなら、これは最高のものでしょう。
ただし、「System.out」のように誰も変更できないため、変数をパブリックとして作成できます。これも、意図と達成したいことに依存します。
クラスがこれまでに複数のインスタンスを持たない場合、どれがより多くのメモリを必要とするかを考えてみましょう:
プライベート静的最終 int ID = 250; またはプライベート最終 int ID = 250;
static はメモリ内にコピーが 1 つだけあるクラス型を参照し、非 static は各インスタンス変数の新しいメモリ位置にあることを理解しました。ただし、内部的に同じクラスの 1 つのインスタンスを比較するだけの場合 (つまり、複数のインスタンスが作成されない場合)、1 つの static final 変数によって使用されるスペースに関してオーバーヘッドはありますか?
これは役立つかもしれません
public class LengthDemo {
public static void main(String[] args) {
Rectangle box = new Rectangle();
System.out.println("Sending the value 10.0 "
+ "to the setLength method.");
box.setLength(10.0);
System.out.println("Done.");
}
}