2016-05-17 11 views
0

有沒有提供這樣的變量聲明優化:javac是否預先計算固定表達式?

final int secondsInDay = 24 * 60 * 60; 

在C++這段代碼甚至不會編譯儘管additional_funct是根本不使用:

#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"將導致字符串池中的字符串"foobar",而不是兩個字符串"foo""bar"

爲了便於閱讀,您應該隨時編寫代碼。如果將它寫爲24 * 60 * 60對於您正在編寫的內容而言更有意義,請使用它。即使它不是在編譯時計算的,我也會認爲這種重複乘法對代碼的性能產生了有意義的影響,並帶有很大的懷疑。

調試您寫84_600而不是86_400的事實的成本要高出幾個數量級。

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),但有一個重要方面迄今尚未提及。

考慮不這樣做。

當然,使用基本int來存儲秒數可能是完全有效的。但是:根據你的環境,以及如何使用事情...這可能是一個更好的設計,在這裏實際使用面向對象建模的力量。含義:如果你想表達的持續時間的時間;那麼爲什麼不使用對象和類來表示這些持續時間?

我見過這麼多的錯誤裏,人們被調用方法

someX.waitForGivenNumberOfSeconds() 

someX.waitForGivenNumberOfSeconds(someValue * 1000) 

只是因爲他們沒有複製粘貼+;並忽略了他們從一個使用毫秒的地方複製過來;而不是秒。即使方法命名爲「給我幾秒鐘」人們通過「毫秒」。或相反亦然。更糟糕的是:通常,唯一可見的指示可能是附加到要調用的方法的源代碼的一些@param durationInSeconds。很容易出錯。以後很容易被改變,並將所有現有代碼渲染爲混亂。

因此,長話短說:只需退後一秒,並決定「OO建模」開銷是否適合您正在處理的「整體解決方案」。