2012-01-23 13 views
2

我環顧四周,無法弄清楚這一點:我有一個實現觀察者模式和List實現的對象,允許在列表中的任何對象上觸發更改事件時將偵聽器添加到列表中,以避免手動向列表中的每個對象添加/刪除偵聽器。當將對象添加到java集合時,它是通過值或引用添加的嗎?

我遇到的問題是,當創建相同List實現的新實例並從現有列表添加對象時,對象更改不會從添加到新列表中的Bean觸發。我的想法是,當向一個集合添加一個對象時,它只是添加一個指向現有對象的指針,在這種情況下,更改通知將在新列表中的對象上觸發,但這不會發生。任何人都可以幫我弄清楚問題可能是什麼?我看到過類似的問題,但沒有一個可以幫助我解決這個問題。

該用例是一個股票掃描器,其中一個列表包含我正在觀察的市場中的所有股票,並且該掃描器列表僅具有通過該標準的股票,但掃描器沒有獲得價格,交易量等更新使用觀察模式觸發。 - Duncan

+1

可能重複[按值傳遞或通過引用在Java?](http://stackoverflow.com/questions/7301637/pass-by-value-or-pass-by-reference-in-java) –

回答

-5

Java對象總是按引用傳遞。因此,除非你的Collection的「add」方法做了別的事情(比如克隆對象或者用它作爲原型等),所有東西都應該可以工作。

我認爲你的問題更多的是通知的邏輯,而不是集合本身。我建議你粘貼一些代碼。

+5

請參閱OscarRyz的答案。它是按值傳遞的,但是,該值是引用的值。 – 5StringRyan

+0

關於通知邏輯的好處,我認爲這可能是我的問題的一部分。 –

-3

是的,在Java中,每個類(但不是簡單類型)都是通過引用傳遞的。

要解決您的問題,您可以使用克隆,如果您的對象支持它。

+0

看到OscarRyz的答案。 – 5StringRyan

9

你的理解是正確的;集合持有對象的引用。例如,這樣的:

final StringBuilder stringBuilder = new StringBuilder(); 
final List<StringBuilder> stringBuilderList = new ArrayList<StringBuilder>(); 
stringBuilderList.add(stringBuilder); 
stringBuilderList.add(stringBuilder); 
stringBuilder.append("yes"); 
System.out.println(stringBuilderList); 

將打印:

[yes, yes] 

因爲只有一個StringBuilder實例,因此附加"yes"是在列表中的每一個元素。

不過需要注意的集合,通過不參考持有這些引用按值。例如,這樣的:

StringBuilder stringBuilder = new StringBuilder("yes"); 
final List<StringBuilder> stringBuilderList = new ArrayList<StringBuilder>(); 
stringBuilderList.add(stringBuilder); 
stringBuilder = new StringBuilder("no"); 
// now stringBuilder refers to a different object than before 
stringBuilderList.add(stringBuilder); 
System.out.println(stringBuilderList); 

將打印:

[yes, no] 

因爲列表的兩個元素是指不同的對象,即使這兩個對象是由相同的變量確定。

想要找出代碼中出現問題的更多幫助,我認爲您必須發佈一個最小程序來演示此問題。

5

按照價值,永遠!

當涉及到對象時,傳遞的值是引用的值,但不是它自己的引用。

See most of these links

的語言,是支持通過引用傳遞(Java不支持這一點)可以執行以下操作:支持通過引用傳遞

Foo foo = new Foo();//create a new object 
foo.name("Old foo"); // label it 
modify(foo); // try to modify it 
// In a language that supports byRef will print "New foo". 
// In Java will print "Old foo" always 
println(foo); 
... 
void modify(Foo foo) { 
    foo = new Foo(); // reference assigned a new different object 
    foo.name("New foo"); 
} 

所以,語言,將會把新對象在方法內部創建傳遞給它們的參考(畢竟它們收到參考)。像C++和VB語言能做到這一點..不支持通過引用(如Java)通

語言將不分配新對象原始參考,Java將其分配到的的副本參考(在參數傳遞創建的一個 - >void modify(Foo foo) {)但原之一,創建之前該方法將保持不變,因此仍與Old foo之一。

+1

恕我直言,說它是「通過引用傳遞」更具信息性。當然,參考是一個價值,但我發現這個參數是用語義來玩的。你可能會說「沒有這樣的東西作爲對象,只有引用的值」。 – Bohemian

+0

@Bohemian物體出口不能從外面到達。說「你得到了參考的價值」是正確的。*一些其他編程語言,如C++或VB可以讓你直接修改參考​​。 – OscarRyz

+1

@Bohemian,雖然我同意你的觀點,擴大了一下就「按值傳遞」將是信息,我不會把它右出「通過引用傳遞」。這意味着Java支持一種'void swap(String a,String b)',它可以在'String x =「X」,y =「Y」中交換引用'x'和'y'; swap(x,y);'(當然,這在Java中是不可能的!)。 –

1

按Java規範,一切都在Java的值傳遞。這個SO discussion有很好的例子說明它是如何工作的。具體閱讀第二個答案。