[英]Is deep copy necessary on passing an ArrayList to a copy constructor?
I'm trying to figure out the best way to implement the code I'm working on. 我正在尝试找出实现我正在研究的代码的最佳方法。
I have two options of how to pass the data to my constructor. 对于如何将数据传递给构造函数,我有两种选择。
First way 第一种方式
private String ISBN;
private String title;
private ArrayList <Person>authors = new ArrayList<>();
private ArrayList <BookCategory>subjectCategories = new ArrayList<>();
public Book (String isbn, String title,
ArrayList <Person>authors, ArrayList <BookCategory>categories) {
//call the checkISBN method
boolean check = checkISBN(isbn);
if (check ==true) {
this.ISBN= isbn;
}
else {
throw new IllegalArgumentException("Invalid ISBN");
}
this.title = title;
for(int index =0; index<authors.size(); index++) {
this.authors.add(authors.get(index));
}
}
Second way 第二种方式
private String ISBN;
private String title;
private ArrayList <Person>authors = new ArrayList<>();
private ArrayList <BookCategory>subjectCategories = new ArrayList<>();
public Book (String isbn, String title,
ArrayList <Person>authors, ArrayList <BookCategory>categories) {
//call the checkISBN method
boolean check = checkISBN(isbn);
if (check ==true) {
this.ISBN= isbn;
}
else {
throw new IllegalArgumentException("Invalid ISBN");
}
this.title = title;
this.authors = authors;
}
Does it make a difference? 这有什么不同吗?
I'm not sure because it seems like it would be unnecessary to declare the Book
with a copy of the Authors ArrayList
instead of the original ArrayList
. 我不确定,因为似乎没有必要使用Authors ArrayList
的副本而不是原始ArrayList
来声明Book
。
What is the correct way to do this, and why? 正确的方法是什么?为什么?
If you copy, you spend some time to gain security. 如果您进行复制,则需要花费一些时间来获得安全性。 If you didn't copy, then a client could construct a Book
with some authors and later change the authors which will be reflected in the Book
: 如果您不进行复制,那么客户可以与一些作者一起构造一Book
,然后再更改作者,这将反映在Book
:
List<Person> authors = new ArrayList<>();
authors.add(new Person("J.K. Rowling"));
Book harryPotter = new Book("some ISBN", "Harry Potter", authors, new ArrayList<>());
// Harry Potter is written by J.K. Rowling.
authors.set(1, new Person("pkpnd"));
// Harry Potter is now written by pkpnd??
If that sounds bad in your use case, you should make a copy. 如果这在您的用例中听起来很糟糕,则应进行复制。
Note that you aren't performing a deep copy, only a shallow copy. 请注意,您不是在执行深层复制,而只是执行浅层复制。 You'll need to create entirely new Person
objects when copying: 复制时,您需要创建全新的Person
对象:
this.authors = new ArrayList<>();
for (Person p : authors) {
this.authors.add(new Person(p.getName()));
}
This is an example of how to make a deep copy of your class with serialization
. 这是一个如何通过serialization
对类进行深层复制的示例。 This ensures everything is a brand new reference: 这样可以确保所有内容都是全新的参考:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
public Person(String name) {this.name = name;}
public String setName(String name) {return this.name = name;}
/**
* make a deep copy with serialization without creating files
* convert class object to a stream of bytes then restore it
*/
public Person deepCopy() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
oos.flush();
oos.close();
bos.close();
return (Person) new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray())).readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
// Test
Person p1 = new Person("Yahya");
Person p2 = p1;
Person p3 = p1.deepCopy();
// change the original object and check if that affect the others
p1.setName("Uknown");
System.out.println("P1: " + p1.name + " ... P2: " + p2.name
+ " ... P3: " + p3.name);
}
}
Output 输出量
P1: Uknown ... P2: Uknown ... P3: Yahya
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.