2011-12-19 70 views
52

在OpenJDK的,對於方法:爲什麼Double.valueof javadoc說它緩存值,當它不?

public static Double valueOf(double d) 

的Javadoc說:

返回表示指定的double值的Double實例。如果不需要新的Double實例,通常應該優先使用此方法,而不是構造函數Double(double),因爲此方法通過緩存頻繁請求的值可能會產生顯着更好的空間和時間性能。

下面是實際的代碼:

public static Double valueOf(double d) { 
    return new Double(d); 
} 

緩存是騙人的!這裏發生了什麼?

+31

該文檔始終是錯誤的。請記住。 – 2011-12-19 13:10:07

+5

你從哪裏獲取代碼? OpenJDK6? OpenJDK7?阿帕奇和諧? GNU類路徑? – scravy 2011-12-19 13:23:15

+0

@scravy我在看OpenJDK7,但是這個代碼在官方的Sun版本中並沒有改變多年。 – 2011-12-19 13:27:04

回答

54

的方法存在多種類型:IntegerLongBigDecimal和他人的文檔始終是相同的:在某些情況下(這是沒有定義),該方法可以返回相同的結果。 AFAIK,緩存只對整數類型實現,並且返回緩存實例的值介於-128和127之間(最常見的值)。對於BigDecimal,緩存當前適用於從0值到Java 的10

後來的版本可能擴展這種行爲爲其他值/多種類型。所以今天使用這個代碼是很明智的,因爲它可能會讓你的代碼更快明天(而且代碼今天不會變慢)。

例如,Java編譯器在生成自動裝箱代碼時使用此API。

6

API的設計者可能不想限制替代實現。那些現在可以自由添加緩存到Double類。

29

沒有什麼不對的API文檔:

這種方法可能產生...

也就是說,實現是允許在這裏做緩存,這是根本不可能用一個構造函數。但是,這不是必需的。但是,由於您有執行緩存的機會,因此此方法應優先於使用構造方法。

+4

+1。恕我直言,關鍵是OP寫入「*實際代碼」,但他提供的是一個*實現。其他實現可以並且確實適用於其他平臺。 (特別是,在固件實現中看到這裏的區別並不會讓我感到驚訝。) – ruakh 2011-12-19 13:19:52

+0

@ruakh我會想到替代實現也會帶有替代javadoc。代碼和javadoc放在一起,它不應該是一個高層次的規範文檔。這不屬於代碼。 – 2011-12-19 13:24:57

+7

java。* classes *的javadoc是*規範,因爲其他廠商不是Oracle編寫Java實現的廠商,他們必須爲所有這些類提供相同的功能。 – 2011-12-19 13:30:14

2

這些valueOf()方法存在於每種數字類型中以支持緩存。實際上,對於Double,它不使用任何緩存,但爲IntegerLong

12

從Java 1.5+,在JVM/JIT保證了Integer小號-127到127緩存所以這就是爲什麼Integer首選的方法是使用valueOf。您通常應該使用valueOf而不是使用double的構造函數,因爲那樣JIT就能夠根據它認爲合適的方式優化您的代碼。例如,考慮下面的循環:

for (Object o: objectList) { 
    o.setValue(Double.valueOf(0.0)); 
} 

在這種情況下,JIT可以預先計算的雙重目標,並重新分配在每次循環相同的值,而如果你使用new Double(0.0);將無法​​它要做到這一點。

+0

+1,用於突出顯示緩存用例。 – Luke 2011-12-19 16:36:59

+2

恭喜,你現在有2013年的代表,新年快樂2013 :) – 2012-12-31 19:49:59

+0

@MohamedSakherSawan謝謝 - 這讓我的一天:) – Deco 2013-01-01 22:25:59

2

請記住,JVM的創建是爲了減少嵌入式設備的代碼大小(主要是) - 這是一個機頂盒操作系統。我曾經在幾個嵌入式Java平臺上工作,對那些「價值」valueOf會更明顯,在某些情況下會節省相當多的空間。

這個方法大多存在,因爲「new」永遠不能使用緩存的實例。 valueOf可以被實現爲使用緩存的實例(否則你只會總是使用新的),並可能在任何證明節省時間的地方執行。如果他們(或你)用一個實際緩存值代替了那個方法,那麼你所有的代碼都會從這個變化中獲得優勢,但是沒有通過提供像「valueOf」這樣的方法來做準備,它永遠不會發生(當然,幾乎從來沒有 - 你可以調整編譯器/字節碼執行器有「新」返回緩存值,但我認爲這會打破一些合同)

所以緩存不是真的謊言,只是一種心態。

+2

你可以參考關於jvm的原因聲明嗎?valueOf方法是新的,用於支持自動裝箱。不應該有這些構造函數,這特別適用於布爾值。 – stolsvik 2011-12-21 21:41:30

相關問題