2016-05-17 1 views
0

な変数宣言のために提供最適化があります:javacは固定式をあらかじめ計算していますか?

final int secondsInDay = 24 * 60 * 60; 

そのadditional_functは一切使用されていないにも関わらず、C++のこのコードもコンパイルされません。

#include <iostream> 

void additional_funct(int num); 


void main() 
{ 
    std::cout << "just a text"; 
} 


void additional_funct(int num) 
{ 
    // For both lines will be shown "divide by zero" 
    int var = 5/0; 
    int another_var = num + (2/0); 
} 

これは、C++コンパイラが最適化を行うことを証明しています実行前に数値リテラルの式をあらかじめ計算しておく必要があります。 同じJavaコードは単純に実行を開始しますが:

package experimental_main; 

public class Experimental_start { 
    public static void main(String[] args) { 
     // Will throw ArithmeticException "by zero" 
     additionalMethod(2); 
     System.out.println("just a text"); 
    } 


    static void additionalMethod(int num) { 
     int var = 5/0; 
     int anotherVar = num + (2/0); 
    } 
} 

私はjavacは、C言語の意味でコードをコンパイルしていないことを理解しています。しかし、おそらくそれはいくつかの他の方法で最適化を提供したり、その優れたが、このように、このような数値リテラルを宣言するために:すべての主要な最適化を行いません

// 24 * 60 * 60 
final int secondsInDay = 86_400; 
+2

「javap -c YourClass.class'」をご覧ください。しかしこれを行うもっと記述的な方法は 'TimeUnit.DAYS.toSeconds(1)'を使うことです。 –

+0

C++コード*はコンパイルして実行します( 'main'のシグネチャを変更した場合)、[警告します](http://ideone.com/DxgXMh)。 –

+0

このコードは例として挙げられています。しかし、ちょうど 'secondsInDay'宣言について:私には恥ずべき=)私は' TimeUnit'を知っていますが、この方法で使うことさえ考えていませんでした。 – Cryptor

答えて

4

はい、javacは、コンパイル時の定数を事前計算します。また、コンパイル時の定数文字列を連結します。 final String s = "foo" + "bar"の場合は、文字列プール内にという文字列があり、2つの文字列ではない"foo"および"bar"となります。

あなたは常に読みやすいようにコードを書く必要があります。 24 * 60 * 60と書いている場合は、あなたが書いていることの意味でより意味があります。コンパイル時に計算されなかったとしても、この繰り返しの乗算がコードのパフォーマンスに大きなインパクトを与えているという懐疑的な主張を扱います。

の代わりに84_600を書き込んだという事実をデバッグするコストは、それよりも大きくなります。

5

javacが、このような表現は、

javacレベルで評価することができます

あなたが表現をコンパイルした場合int secondsInDay = 24 * 60 * 60;あなたは、

public static void main(java.lang.String[]); 
descriptor: ([Ljava/lang/String;)V 
flags: ACC_PUBLIC, ACC_STATIC 
Code: 
    stack=1, locals=2, args_size=1 
    0: ldc   #2     // int 86400 
    2: istore_1 
    3: return 
    LineNumberTable: 
    line 7: 0 
    line 9: 3 

そして#2のようなものは、定数プール内に存在になるだろう

Constant pool: 
... 
#2 = Integer   86400 

表示されているとおり、この値は86400と評価されました。

1

他の回答はすべて正しいです(そして最終的にはthis questionに重複します)。しかしこれまで述べていない重要な側面が1つあります。

このようにしないでください。

もちろん、プリミティブintを使用して秒数を格納することは完全に有効です。しかし、あなたの文脈や、物事がどのように使われているかによっては、OOモデリングの力を実際に使うよりはるかに良いデザインかもしれません。意味:の時間をと表現する場合は、その期間を表すためにオブジェクトやクラスを使用しないのはなぜですか?

私は、人々は、彼らがコピー+ペーストをしたからといって

someX.waitForGivenNumberOfSeconds(someValue * 1000) 

よう

someX.waitForGivenNumberOfSeconds() 

メソッドを呼んでいたので、多くのバグを見てきました。彼らはミリ秒を使用していた場所からコピーしたことを見落としました。秒ではありません。 "私に秒を与える"という名前のメソッドでも。人々は "ミリ秒"を過ぎた。またはその逆。さらに悪いことに、あまりにも頻繁に表示される唯一の表示は、呼び出すメソッドのソースコードに添付された@param durationInSecondsです。だから間違ってしまうのは簡単です。後で簡単に変更でき、既存のコードをすべて混乱状態にすることができます。

短いストーリー:ちょっと戻って、「OOモデリング」オーバーヘッドがあなたが取り組んでいる「全体的な解決策」に適しているかどうかを判断してください。

関連する問題