gpt4 book ai didi

java - 在构造函数中将对象添加到静态 ArrayList 是不好的做法吗?

转载 作者:行者123 更新时间:2023-12-03 23:14:12 24 4
gpt4 key购买 nike

如标题所示,我想知道下面的代码是否是不好的做法?我已经读到,由于垃圾收集问题,这种方法可能不好,但是其他帖子说这是一种可接受的存储对象的方式。

是不是新建一个类纯粹用来处理公司列表比较好?

谢谢。

public class Company{
private static ArrayList<Company> allCompanies = new ArrayList<>();
String name;
String email;
String phoneNumber;
String postalAddress;

public Company(String name, String email, String phoneNumber, String postalAddress){
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber;
this.postalAddress = postalAddress;
allCompanies.add(this);

}

public static ArrayList<Company> getAllCompanies() {
return allCompanies;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPhoneNumber() {
return phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

public String getPostalAddress() {
return postalAddress;
}

public void setPostalAddress(String postalAddress) {
this.postalAddress = postalAddress;
}



}

最佳答案

代码的主要问题是它有意想不到的副作用。

你应该能够构造一个新的 X,让它消失,然后让垃圾收集器清理它。在这种情况下,新公司将永远存在。您还引入了线程同步问题 - 既因为创建新对象现在可以同时添加到同一个列表中,也因为您在 Company 对象完全构建之前泄漏了它。

例如,如果线程 A 在扫描列表的同时线程 B 创建了一家新公司,那么创建将失败并出现并发修改异常。如果您设法避免这种情况,那么线程 A 可能会在线程 B 完成构建公司之前开始尝试使用该公司!

正确的做法是拥有一个工厂对象,并让工厂负责创建新的 Company 对象并将它们存储在列表中。您可以将公司构造函数包设为私有(private),以防止人们通过工厂以外的方式意外创建它们,您可以记录工厂提供或不提供多少线程安全,并实现您需要的安全级别。

例如A.java

public class A {
A() { // Note none-public constructor
}
}

AFactory.java(与 A.java 在同一个包中,因此它可以访问构造函数)

public class AFactory {
private final List<A> aList = new ArrayList(a);
public A buildA() {
A a = new A();
synchronized(aList) {
aList.add(a);
}
return a;
}
}

或者如果你不需要线程安全:

public class AFactory {
private final List<A> aList = new ArrayList<>(a);

public A buildA() {
A a = new A();
aList.add(a);
return a;
}
}

但在这种情况下,您应该始终在 Javadoc 注释中说明工厂不是线程安全的,如果从多个地方使用,应该在外部进行同步。

根据使用情况,您可能会发现 Map(如果您希望能够通过某个键找到 A)或 Set(如果您希望防止重复 A)效果更好。

public class AFactory {
private final Map<Key, A> aMap = new HashMap<>(a);

public A buildA(Key key) {
synchronized (aMap) {
A a = aMap.get(key);
if (a == null) {
a = new A();
aMap.put(key, a);
}
}
return a;
}

public A getA(Key key) {
synchronized(aMap) {
return aMap.get(key);
}
}
}

请注意,您可能想要研究一些并发集合 (java.util.concurrent) 类,而不是自己管理同步。

关于java - 在构造函数中将对象添加到静态 ArrayList 是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20678654/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com