第
在Java中,每個對象變量都是引用。對象不能被值傳遞,只有原語可以(並且總是)。那麼,這有點誤導。該參考是按值傳遞,但你能想到的一切作爲參考,只要不是在C++的觀點。
也許是最容易使用的例子。
SomeObject foo;
public void doSomething(SomeObject bar) {
bar.whatever();
bar = new SomeObject();
bar.someOtherMethod();
}
public void doStuff() {
foo = new SomeObject();
doSomething(foo);
}
所以,foo
是的SomeObject
實例的引用。當doSomething
被調用時,該參考值被複制到bar
,所以現在foo
和bar
是相同的SomeObject
引用。
行bar.whatever()
對foo
所指的同一對象調用whatever
。
bar = new SomeObject()
意味着foo
和bar
現在參閱不同SomeObject
實例,所以someOtherMethod
是不稱爲該foo
是指在對象上。
這是C++完全不同的,其中
void doSomething(SomeObject& bar) {
bar = whatever;
}
具有完全不同的含義。你真的不應該用C++來考慮Java。
關於您的示例,String
s在Java中是不可變的,所以即使對象可能按值傳遞也沒關係。
關於你的第二個例子,如果你想返回一個對象,調用者不能用污染的內部狀態,那麼,是的,你需要有一個拷貝構造函數(或等價的東西)。
例如:
class ClassWithInternalList {
private List<String> reallyImportantData;
public List<String> getImmutableViewOfData() {
// Take advantage of the java.util.Collections tool for making a List immutable.
return Collections.unmodifiableList(reallyImportantData);
}
public List<String> getSafeCopyOfData() {
// Return a copy that the caller can modify without changing reallyImportantData.
return new ArrayList<String>(reallyImportantData);
}
public List<String> justGetTheData() {
// Return a reference to reallyImportantData that the caller can modify at will.
return reallyImportantData;
}
}
可以選擇根據情況適當類型的返回值(正常參考,不可變的視圖或複製)。根據你正在做的事情,三種選擇中的任何一種或全部都是合適的。
java.util.Collections
可以很容易地獲得Collection
的不可變視圖,但對於自定義類您需要做自己的不變性。
請記住,如果存在可變性問題,則只需執行此操作。您的MyCustomObject
示例仍然是不可變的(因爲調用者無法更改返回的MyCustomObject
實例中的任何狀態),所以問題仍然有點不切實際。
'字符串'是不可變的;沒有意義返回一個新的。 – alf
Java總是按價值傳遞。對象引用也是按值傳遞的。 –