2012-03-29 69 views
0

上Java基礎的一些問題, 以下函數返回節點類型的對象預先返回的對象修改的java

class DS{ 
    public Node getNode(int index){ 
     return nodeList.get(index); 
    } 
} 

public void test1(){ 
    DS ds = new DS(); 
    Node node = ds.getNode(3); 
    // will the change in node variable(of test1()) change the actual Node object in ds? 
    // Is there a simple way to create a copy to prevent source node's data modification? 
} 

感謝。

回答

2

DS類的getNode()方法返回參考到存儲在nodeList中的節點。因此,如果您的Node類可以進行變異(通過setter方法或直接訪問其字段),那麼是的,test1中的代碼將更改底層(現在是共享的)節點引用。

如果你想「斷開」返回的從節點的節點在數據存儲,那麼你可以先clone它。您的節點類將需要實現Cloneable並覆蓋clone()方法。如果您在節點只圖元,那麼你可以簡單地做:

public Object clone() 
{ 
    return super.clone(); 
} 

如果在節點的其他對象,那麼默認的克隆操作只會讓淺拷貝,你將需要使你的克隆方法更廣泛,以至於它使深拷貝。從Object.clone()的Javadoc:

按照慣例,此方法返回的對象應該獨立於此對象(正在克隆)。爲了實現這種獨立性,可能有必要在返回之前修改super.clone返回的對象的一個​​或多個字段。通常,這意味着複製包含被克隆對象的內部「深層結構」的任何可變對象,並將這些對象的引用替換爲對這些副本的引用。如果一個類只包含原始字段或對不可變對象的引用,那麼通常情況下,super.clone返回的對象中的字段不需要修改。

您的DS類的變化將是:

public Node getNode(int index){ 
    return (Node) nodeList.get(index).clone(); 
} 
1

是的,修改test1()中的node將修改ds列表中的對象。這是因爲它是對同一個對象的引用。

如果要修改node而不影響原始文件,則需要複製 - 例如,執行new Node(),然後將所有字段從舊的複製到新的。您也可以實現Cloneable接口並使用Object類提供的clone()方法。或者給Node一個構造函數,它將另一個Node作爲參數並複製其數據。

+0

僅供參考,接受同一類型的另一個對象,並創建一個副本從它(不出所料)「拷貝給一個構造函數的名稱構造函數「 – Bohemian 2012-03-29 01:35:59

+0

現有的默認克隆方法不夠嗎? 我應該明確實施嗎? – sravanreddy001 2012-03-29 01:39:32

+1

@mrb - 如果你在一個沒有實現'Cloneable'的對象上調用clone(),你會得到一個'CloneNotSupportedException'。參考:用於'Cloneable'的javadocs。 – 2012-03-29 01:46:48

0

是的。您只需將引用添加到(相同)節點對象。任何改變都會反映出來(儘管有線程問題)。

要返回節點的副本代替,這樣做:

創建一個「拷貝構造函數」:

public Node(Node node) { 
    // Copy all the fields across 
    this.field1 = node.field1; 
    this.field2 = node.field2; 
    // etc 
} 

從你的方法,使用拷貝構造函數返回一個副本:

public Node getNode(int index){ 
    return new Node(nodeList.get(index)); 
} 

此代碼模式被稱爲「安全發佈」 - 你的API安全提供對象給調用者,你的類是ACCID安全對其狀態進行修改(即字段)。

+0

我可以做什麼來創建一個不同的對象來返回? – sravanreddy001 2012-03-29 01:37:14

+0

我會*不*使用'可克隆'。我只是簡單地製作一個拷貝構造函數 - 參見編輯答案 – Bohemian 2012-03-29 22:48:09

0

正如其他人提到的,答案是肯定的。

沒有提到的一個選項是使Node對象immutable

+0

它並不是我不想進行更改, 我想進行更改,但我需要一份不是原創的副本。因此,如果我們不使用新的關鍵字(某些地方在代碼中),它只是對該對象的引用。它是否正確? – sravanreddy001 2012-03-29 01:41:05