我在java中编码,但我认为这个问题与一种语言无关。
我的问题发生在我们与同事谈论对象列表时,这是一个类的领域。我说我总是初始化List with和空列表。所以我可以直接使用这个列表的getter而不检查它是否为null:
myObject.getList().add(o)
他说我喜欢不为列表创建一个getter,因为他不想检查列表是否为null,因此他创建了一个“addItemToMyList”方法来将项添加到列表中。通过这种方式,他可以在此方法中控制列表不为空(如果是这种情况,则创建它),并且毫无疑问以这种方式使用列表。
我认为为我们使用的每个列表编写很多方法可能需要做很多工作(获取大小,添加,删除......)。
摘要:
上课:
class MyObject {
private List<X> list = new ArrayList<X>();
public List<X> getList() { return list; }
}
用法:
MyObject myObj = new MyObject();
myObj.getList().add(anObject);
上课:
class MyObject {
private List<X> list;
public void addItemToList(X item) {
if (list == null) list = new ArrayList<X>();
list.add(item);
}
... // methods to get the size, remove item...
}
用法:
MyObject obj = new MyObject();
obj.addItemToList(anObject);
上课:
class MyObject {
private List<X> list;
public List<X> getList() { return list; }
public List<X> setList(List<X> list) { this.list = list; }
}
用法:
MyObject myObj = new MyObject();
if (myObj.getList() == null) myObj.setList(new ArrayList<X>());
myObj.getList().add(anObject);
对于列表和一般复杂字段,有什么好方法?
答案 0 :(得分:2)
我认为这是主观的,但是:
-
class MyObject {
private final List<X> list = new ArrayList<>();
public void addItemToList(X item) {
list.add(item);
}
... // methods to get the size, remove item...
}
现在让我们假设在稍后阶段你想要使该类线程安全并添加一个需要2个操作原子化的方法,很容易添加相关代码而不改变其他任何东西:
class MyObject {
private final List<X> list = new ArrayList<>();
private final Object listLock = new Object();
public void addItemToList(X item) {
synchronized(listLock) {
list.add(item);
}
}
public void addItemToListIfEmpty(X item) { //let's say you need that method
synchronized(listLock) { //you can make the operation atomic
if (list.isEmpty()) {
list.add(item);
}
}
}
... // methods to get the size, remove item...
}
而在解决方案1中,您需要更改使用该列表的所有代码。
如果主叫代码确实需要整个列表,您可以随时返回副本,以便他们可以使用它。
答案 1 :(得分:1)
一般来说,我更喜欢第一种方法 - 只是因为list
是你的代码的一部分(在本例中是你的类),你可以确保列表总是非空的,从而节省了所有的支票。关于第二种和第三种方法 - 所有访问者都需要进行此类检查,并且会产生不需要的代码重复。
作为奖励,使用第一种方法将允许您将列表指定为final
实例,使您的类“更”线程安全。