實作 Cloneable 介面並覆寫 clone() 方法,但發現克隆後的對象中 InputStream 屬性仍指向同一個物件(淺拷貝),修改其中一個會影響另一個。
super.clone() 僅執行淺拷貝:基本類型複製值,引用類型複製引用地址。JVM 不會自動深度複製引用指向的對象(如 InputStream、自定義對象等)。
在 clone() 中將 InputStream 讀取到 ByteArrayOutputStream,再構建新的 ByteArrayInputStream 賦值給克隆對象:
@Override
public Object clone() throws CloneNotSupportedException {
CloneTest cloneTest = (CloneTest) super.clone();
// 深度複製 InputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
baos.flush();
// 建立新的輸入流
cloneTest.inputStream = new ByteArrayInputStream(baos.toByteArray());
} catch (IOException e) {
e.printStackTrace();
throw new CloneNotSupportedException("InputStream 複製失敗: " + e.getMessage());
}
return cloneTest;
}
InputStream 必須可讀且非無限流(如網絡流需先緩存)。List、自定義對象),同樣需逐一深度複製。Java 原生 clone() 只做淺拷貝。對於 InputStream、集合、自定義對象等引用類型,必須在 clone() 中顯式編碼實現深度拷貝,確保克隆對象與原對象完全獨立。