[英]Deep copy of an object array
我想使用構造函數制作對象數組的深層副本。
public class PositionList {
private Position[] data = new Position[0];
public PositionList(PositionList other, boolean deepCopy) {
if (deepCopy){
size=other.getSize();
data=new Position[other.data.length];
for (int i=0;i<data.length;i++){
data[i]=other.data[i];
}
但是,由於某種原因,我上面的內容不起作用。 我運行了自動化測試,但這些測試失敗了。 所以這里有一個錯誤,我不確定它是什么。
你實現的是一個淺拷貝。 要實現深拷貝,你必須改變
data[i] = other.data[i];
某些將other.data[i]
的副本分配給data[i]
。 您如何執行此操作取決於Position
類。 可能的替代方案是:
復制構造函數:
data[i] = new Position(other.data[i]);
工廠方法:
data[i] = createPosition(other.data[i]);
克隆:
data[i] = (Position) other.data[i].clone();
筆記:
clone
方法只有在Position
明確支持它時才有效,這通常被認為是一種劣質的解決方案。 此外,您需要注意clone
的本機實現(即Object.clone()
方法)執行淺拷貝1 。 事實上,在 Java 中實現深度復制的一般問題是復雜的。 在Position
類的情況下,人們會假設屬性都是原始類型(例如 ints 或 doubles),因此深拷貝與淺拷貝沒有實際意義。 但是如果有引用屬性,那么你必須依靠復制構造函數/工廠方法/克隆方法來做你需要的那種復制。 在每種情況下都需要對其進行編程。在一般情況下(您必須處理循環),這很困難並且需要每個類實現特殊方法。
還有另一種可能的方法來復制對象數組。 如果數組中的對象是可序列化的,那么您可以通過使用ObjectOutputStream
和ObjectInputStream
serialize 來復制它們,然后反序列化數組。 然而:
transient
字段的值。不建議通過序列化復制。 最好支持克隆或其他一些方法。
總而言之,在 Java 中最好避免深度復制。
最后,為了回答你關於Position
類復制構造函數的問題,我希望它是這樣的:
public class Position {
private int x;
private int y;
...
public Position(Position other) {
this.x = other.x;
this.y = other.y;
}
...
}
正如@Turtle 所說,不涉及魔法。 您實現了一個構造函數(手動),它通過從現有實例復制來初始化其狀態。
1 - 指定clone()
的 Object 實現執行淺拷貝,但這可能會被覆蓋。 clone
的 javadoc 指定“合同”如下:
"創建並返回此對象的副本。"復制"的確切含義可能取決於對象的類。一般的意圖是,對於任何對象 x,表達式:
x.clone() != x
將是true,並且表達式:x.clone().getClass() == x.getClass()
將是 true,但這不是絕對要求。雖然通常情況下是:x.clone().equals(x)
為真,這不是絕對要求。”
“合同”中沒有任何內容涉及深復制與淺復制。 因此,如果您打算在此上下文中使用clone
,您需要知道實際的類clone
方法的行為方式。
當你說:
data[i]=other.data[i];
您只是在復制引用列表(假設這是一個對象數組)。 如果要進行深拷貝,則需要使用new
為數組中的每個對象創建一個新實例。
而不是說:
data[i]=other.data[i]
您需要為Position
創建一個復制構造函數(換句話說,Position 的構造函數接受另一個Position
並復制其中的原始數據)並說data[i]=new Position(other.data[i]);
基本上你的“深拷貝”構造函數PositionList
是一個拷貝構造函數,雖然拷貝構造函數確實傾向於表示一個深拷貝,所以deepCopy
參數是不必要的。
這是我使用的一個函數:
function copy(arr) {
return arr
.map(x => Object
.keys(x)
.reduce((acc, y) => {
acc[y] = x[y]
return acc
}, {}))
}
它僅適用於具有單個級別的對象的數組。
這應該是一個“深”副本
int [] numbers = { 2, 3, 4, 5};
int [] numbersClone = (int[])numbers.clone();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.