2013-03-26 59 views
0

我有我的代碼中的字符串列表。我將該字符串列表傳遞給一個函數並對其進行修改(我從列表中添加/刪除了少量元素)。但我不希望這些更改反映在調用者函數中。這些更改只應反映在被調用函數中。但是因爲對象是通過引用傳遞的,所以我認爲這兩個函數中的變化都會反映出來。我怎樣才能避免這一點。請幫助Java數組列表和對象傳遞

+1

的ArrayList newArrayList =(ArrayList的)oldArrayList.clone(); – Code2Interface 2013-03-26 05:15:44

+0

增加了額外的位:如果列表中的對象不是不可變的,請注意列表中的對象也可以在被調用函數中更改。列表克隆將創建淺拷貝而不是深拷貝。所以如果你想保護列表中的對象1)做深層克隆2)使對象不可變。 – 2013-03-26 05:23:13

回答

1

可以使用Clone方法。

caller(ArrayList<String> a) 
{ 
    callee((List<String>)a.clone()); 
} 

callee(List<String> aCloned) 
{ 

} 
+0

據我所知,'List'沒有'clone()'方法,因爲它沒有實現'Cloneable'。它的'ArrayList'就是這麼做的。 – SudoRahul 2013-03-26 05:23:16

+0

@ R.J'List'是一個接口,因此它沒有任何方法。 '.clone()'方法在'Object'中定義,並且直覺上與'Cloneable'接口無關。檢查[文檔](http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html) – madth3 2013-03-26 05:28:37

+0

@ madth3 - 感謝您糾正我。但是我的編輯仍然是正確的,因爲你仍然不能在'List a'上調用'clone()'方法,但是可以調用'ArrayList a'。 – SudoRahul 2013-03-26 05:33:53

1

在將對象傳遞給函數之前,您必須複製對象。

1

在子方法中使用原始數組列表的新ArrayList。

2

裏面的方法,你可以明確地使列表的副本:

private void method(ArrayList<String> list) { 
    ArrayList<String> copy = new ArrayList<String>(list); 
    // Rest of the method 
} 
+0

是否工作?我認爲它仍然會給列表中的對象提供相同的參考。 – iMBMT 2013-03-26 05:24:57

+1

@takrbuiam如果有疑問,請查看文檔:[ArrayList API](http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html)。對於任何Java開發人員來說非常重要的工具 – madth3 2013-03-26 05:32:18

+0

@ madth3是的,我知道。我已經嘗試過這種方法。我相信它不會複製對象。它會給同一個對象的參考。 – iMBMT 2013-03-26 05:54:16

1

通常不建議使用clone方法。看到這個clone(): ArrayList.clone() I thought does a shallow copy

不過你可以試試這個方法

public void doOperation(List<String> list){ 
    List<String> duplicateList = new ArrayList(list); 
    // add, or delete stuff on duplicateList 
} 

在這裏,你使用ArrayList的構造給你這是在傳遞的列表的新副本。

+0

是的,列表的新參考文獻給出了相同的對象參考。 – iMBMT 2013-03-26 05:27:25

+1

但是,無論您對此列表所做的更改都不會影響原始列表。由於'String'對象是不可變的,我猜你應該沒有問題。 – midhunhk 2013-03-26 05:31:32

1

你必須使用循環手動從舊列表中創建新列表,並且需要傳遞給該方法。 即

List<String> list=new ArrayList<>(); 
    list.add("first"); 
    list.add("last"); 
    List<String>list2 =new ArrayList<String>(); 
    for(String value:list) 
    { 
    list2.add(new String(value)); 
    } 
    System.out.println("list2-->"+list2); 

new ArrayList<String>(list);因爲是給列表的新的基準,但該對象仍然具有相同的參考。

編輯:

public class ArrayCopy { 


    public static void main(String[] args) { 

     ArrayCopy arrayCopy=new ArrayCopy(); 
     arrayCopy.copyData(); 

    } 
    public void copyData() 
    { 
     List<Test> oldList=new ArrayList<Test>(); 
     oldList.add(new Test("1",10)); 
     oldList.add(new Test("2",45)); 
     List<Test> newList =new ArrayList<Test>(oldList); 
     System.out.println("newList-->"+newList); 

     /** 
     * New Copy of Data 
     */ 
     List<Test> newList1 =new ArrayList<Test>(); 
     for(Test test:newList) 
     { 
      newList1.add(copyProperty(test)); 
     } 
     System.out.println("newList-->"+newList1); 
    } 
    private Test copyProperty(Test test) 
    { 
     Test newTest=new Test(test.getId(), test.getNumber()); 
     return newTest; 
    } 
    class Test{ 
     String id; 
     int number; 
     public Test(String id,int number) { 
      this.id=id; 
      this.number=number; 
     } 
     public String getId() { 
      return id; 
     } 
     public void setId(String id) { 
      this.id = id; 
     } 
     public int getNumber() { 
      return number; 
     } 
     public void setNumber(int number) { 
      this.number = number; 
     } 
    } 
} 
+0

如果'list'中的對象可能會改變,那麼你會是對的,但由於'String's是不可變的,所以創建副本是沒用的。鑑於使用'ArrayList'構造函數的解決方案是好的。 'Cloneable'與'.clone()'方法無關。 – madth3 2013-03-26 05:47:57

+0

@ madth3請參閱我的可編輯答案。它有測試對象。可以嗎?它仍然給予相同的客體參考。請參閱調試模式。 – iMBMT 2013-03-26 06:02:53

+0

我一直都認爲兩個列表中的元素都是一樣的。我建議閱讀[不可變對象](http://www.javapractices.com/topic/TopicAction.do?Id=29)來理解爲什麼在某些情況下它並不重要。 – madth3 2013-03-26 06:16:21