Java で static final 定数が本当に必要ですか?
次のコードがあるとします。
public class Test {
public static final int A = 1234;
public static int getA()
{
return 1234;
}
}
次の 2 つのケースの効率を比較していただけますか。
Test.A
Test.getA()
Java で static final 定数が本当に必要ですか?
次のコードがあるとします。
public class Test {
public static final int A = 1234;
public static int getA()
{
return 1234;
}
}
次の 2 つのケースの効率を比較していただけますか。
Test.A
Test.getA()
JIT コンパイラーを想定すると、効率に目立った違いはないはずです。少なくとも、アプリケーションの実行速度に大きな違いをもたらすほどではありません。
ただし、柔軟性が大幅に向上しています。値をメソッドにカプセル化することは、後で値の計算方法を変更できるため、ほとんどの場合に適しています。
この規則の注目すべき例外は、たとえば数学の世界からの純粋な定数Math.PI
です。この基本的な定数の値が変更される可能性がないため、へのアクセスをカプセル化することはあまり意味がありません。プログラムで値を取得する方法を切り替えます。
定数はstatic
final
、メソッドから返されるリテラル値とは異なる動作をします。Java コンパイラは、コンパイル時にこれらを使用する場合もあります。
一例として、
public static boolean DEBUG = false;
...
if (DEBUG)
{
...do something...
}
対。
public boolean debug()
{
return false;
}
...
if (debug())
{
...do something 2...
}
最初のケースでは、条件と ...何かを行う... コードは、コンパイルされたバイトコード (クラス ファイル) に含まれません。2 番目のケースでは、条件と ...do something 2... コードが含まれますが、実行されることはありません。この場合、JIT は実行時にコードを削除するために十分な分析を行う場合があります。
Java の初期の頃、JIT は存在しなかったか、リテラル値を返す単純なメソッドを最適化するほど賢くありませんでした。次に、パフォーマンスのために一定の値が必要でした。外部クラス (public/protected static final 定数の場合) がコンパイル時にそのバイトコードに焼き付けられた値を持つことを念頭に置いておけば、この方法で定数を定義する方が便利です。実行時にソース クラスから値を取得するのではなく、
効率の面では、多くの場合、JITtest.getA()
と同等に削減できます。test.A
それでも、違いはせいぜい無視できる程度です。
Java で static final 定数が本当に必要ですか?
いいえ。ただし、割り当ての繰り返しを防ぐのに役立ちます。
static final 変数は外部コードで変更できないため、カプセル化する必要はありません。
また、パラメーターのない静的メソッドは、メソッドが静的であるため、オブジェクトの状態へのアクセスを示唆していますが、これは嘘です。
コンパイラーに関しては、効率に大きな違いはないはずですが、プログラムの読みやすさとコードの自己文書化に関しては、static final の方が優れており、実績のあるオプションです。
あなたが示すケースはかなり些細なことであり、それは意図されていると私は信じています。最初のケースは、スタックへの呼び出しが1つ少ないため、より直接的で効率的ですが、2つを組み合わせる方がコーディングスタイルが優れていると思います。クラスでこの変数を使用する場所はこれだけではないと思います。
public class Test {
public static final int A = 1234;
public static int getA()
{
return A;
}
public static int doSomething()
{
int result = A * 10;
//do more stuff
return result;
}
}
これにより、変数を変更する必要がある場合にのみ1つの場所で変数を変更し、プログラム全体で期待される結果を得ることができます。個人的には、getメソッドを使用する際の一貫性のために、int Aをプライベートにします。これは、クラスの設定方法です。このようにして、変数名の後に「()」が必要かどうかを思い出せないという問題に遭遇することはなく、クラス外にあるすべての変数に同じ方法でアクセスします。これのほとんどは単なるコーディングスタイルであり、正しいか間違っているかのどちらでもありません。