2016-01-02 26 views
2

我知道Java是通過引用或按值傳遞的問題正在擊敗死馬,但我確實有關於內存使用情況的問題。在變量之間傳遞大量數據時最大限度地減少內存使用量

我理解Java現在的方式是:

public class MyInt{ 
    int value; 
} 

MyInt x; 
MyInt y; 
x = new MyInt(3); // value of x is now 3 
y = x;    // y now points to same object that x points to 
y.setValue(1);  // value of said object is now 1 
x.getValue();  // should return 1 instead of 3 

但我的問題是內存密集型它是如何設置這個新y?例如:如果明特的數值是一些非常非常大的圖像,而不是一個整數,

x = new MyImage("very large image"); // eats memory depending on size of image 

自然會佔用大量的內存有圖像加載如果它是非常大的。我只是想確保當我打電話

y = x; // y now points to same image that x does 

y只是到x右側已經指向的對象的引用?所以當我撥打y = x;只要該圖像已經通過初始化x加載,無論圖像有多大都不會造成內存密集。

這是正確的嗎?我應該避免將同一個非常大的圖像多次加載到內存中的哪些缺陷?

+0

如果您擔心可能多次使用_same_參數調用'new MyImage(「some string」)',並且它會創建同一大圖的多個副本,那麼您可以使用緩存來避免問題。像HashMap這樣的'Map'將是維護這種緩存的一種簡單方法。 – ajb

+0

'這是否正確?' - 是的,y和x只保存大對象的內存地址。內存地址在大多數系統上是一個整數(小)。 –

回答

0

你是對的,當你打電話給y=x它會簡單地設置y來指代「非常大的圖像」的位置。內存中仍然只有1個對象,它們將被xy引用。

爲避免在存儲器中一次又一次加載非常大的圖像,只是不要再次使用該圖像創建新對象。避免深層複製對象。

3

是的你是對的,任何非原始引用變量的非原始實例賦值都只是引用賦值。

因此,如果有一個內存位置爲x說mem1那麼y = x將使y指向mem1。現在,即使x指向一個新的內存位置mem2,y仍然會指向mem1。所以這是一個需要避免的陷阱。

您幾乎永遠無法加載一個非常大的對象多次而不會先知道它,因爲您要麼創建調用構造函數的新對象,要麼使用某種形式的clone()方法。

與大型對象無關但與Java中的引用相關的一個陷阱是傳遞給方法的引用變量不能被取消引用。

所以假設有一個方法dereferenceMe(MyInt x) {x = new MyInt();}它不會改變調用方法中x的實際引用。由於Java將通過值傳遞引用,這意味着它會創建引用變量的副本,並將該副本傳遞給方法。

+0

關於解引用的最後一點。這是否意味着你現在有兩個MyInt引用? –

+0

是的,一個在調用者方法中,另一個在調用方法中。 – 11thdimension

+0

在c#等其他編譯語言中,它的工作原理是否相同? –

相關問題