[英]How to implement immutable and read-only versions of mutable objects effectively?
語境:
public interface _Data {
public String getData();
}
public class _PackageAPI {
DataHolder holder;
public void createHolder(String data) {
holder = new DataHolder();
holder.setData(data);
}
public void mutateHolder(String data) {
holder.setData(data);
}
public _Data getSnapshot() {
return DataSnapshot.from(holder.getData());
}
public _Data getReader() {
return holder.readOnly();
}
}
class DataHolder {
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public _Data readOnly() {
return new _Data() {
@Override
public String getData() {
return DataHolder.this.data;
}
};
}
}
class DataSnapshot {
public static _Data from(String data){
return new _Data() {
@Override
public String getData() {
return data;
}
};
}
}
package clientPackage;
import data._Data;
import data._PackageAPI;
public class ExampleRunner {
public static void main(String[] args) {
_PackageAPI handler;
System.out.println("Creating...");
handler = new _PackageAPI();
handler.createHolder("INITIAL DATA");
System.out.println("Done creating...");
_Data initialSnapShot = handler.getSnapshot();
_Data initialReader = handler.getReader();
System.out.println("initialSnapShot holds :" + initialSnapShot.getData() );
System.out.println("initialSnapShot class :" + initialSnapShot.getClass() );
System.out.println("initialReader class :" + initialReader.getClass() );
System.out.println("initialReader holds :" + initialReader.getData() );
System.out.println("Mutating...");
handler.mutateHolder("MUTATED DATA");
_Data subsequentSnapShot = handler.getSnapshot();
_Data subsequentReader = handler.getReader();
System.out.println("Done mutating...");
System.out.println("initialSnapShot holds :" + initialSnapShot.getData() );
System.out.println("initialReader holds :" + initialReader.getData() );
System.out.println("subsequentSnapShot holds :" + subsequentSnapShot.getData() );
System.out.println("subsequentReader holds :" + subsequentReader.getData() );
}
}
Creating...
Done creating...
initialSnapShot holds :INITIAL DATA
initialSnapShot class :class data.DataSnapshot$1
initialReader class :class data.DataHolder$1
initialReader holds :INITIAL DATA
Mutating...
Done mutating...
initialSnapShot holds :INITIAL DATA
initialReader holds :MUTATED DATA
subsequentSnapShot holds :MUTATED DATA
subsequentReader holds :MUTATED DATA
第一個問題:給定getSnapshot()返回一個_Data(class:DataSnapshot $ 1),其方法getData()返回“真實”數據引用,即DataHolder object的變量數據的內容,這是安全的還是可能的變異 DataHolder 利用對此參考的訪問? 如果是,如何?
縮短的第一個問題:是否可以僅使用參考來改變參考引用的 memory 的內容?
(當然解決方案是克隆被引用的字符串。)
第二個問題:無論如何都要改變 DataSnapshot$1(_Data 的“不可變”版本)實例?
第三個問題:給定 DataHolder$1(_Data 的“只讀”版本)在內部持有對提供它的 DataHolder 實例的引用,公開這樣的 DataHolder$1 是否安全,或者無論如何都會弄亂 DataHolder$1 中的 DataHolder 實例object?
編輯:如果有的話,我會放一個偏執狂的標簽
這是安全的還是以某種方式可以利用對該參考的訪問來改變
DataHolder
? 如果是,如何?
由於getData
返回一個不可變的String
,因此調用者無法通過返回的引用更改任何內容。 您也不能通過String
訪問DataHolder
。 為什么String
會知道您的DataHolder
class?
反正有變異
DataSnapshot$1
嗎?
不,因為它是一個匿名的內部 class 只有一個返回參數的方法。 參數是按值傳遞的,因此您無需擔心調用者會在另一端更改其值。 它也是一個String
,這意味着調用者也不會改變 object 。
您可能會問這個問題,因為您看到了initialReader
的變化。 好吧,由於DataHolder$1
是可變DataHolder
的內部 class ,因此即使它沒有任何修改器方法,它也不是真正不可變的。
公開這樣的
DataHolder$1
是否安全,或者無論如何都會弄亂DataHolder$1
object 中的DataHolder
實例?
無法從內部 class 訪問外部 class ,因此由於DataHolder$1
中沒有突變器方法,因此您無法從外部對DataHolder
進行突變,只有DataHolder$1
。
但是,如果DataHolder
發生變化,這些變化將反映在DataHolder$1
上(如您的示例代碼所示),我認為這違背了不變性的目的。
這是我在這種情況下實現不變性的方法。
我會讓DataHolder
實現_Data
。 DataHolder
當然可以做到這一點,不是嗎? 畢竟它有一個String getData()
方法! DataHolder
將有一個asReadOnly
方法,該方法創建this
副本並返回_Data
。 事實上,我_Data
重命名為ReadOnlyData
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.