假设我有以下类,列表为字段:
sysinfo
每次添加/删除元素时,确保列表处于有效状态的最佳方法是什么?? (目前class Group {
private List<Tile> tiles;
public Group(List<Tile> tiles) {
this.tiles = tiles;
}
public Group() {
this(new LinkedList<>());
}
public List<Tile> getTiles() {
return tiles;
}
}
课程不包含任何制定者,因此我不必担心要修改的元素。)
一种可能的方法是添加布尔字段Tile
,以及更新valid
的方法,每次添加/删除元素后调用:
valid
使用示例:
class Group {
// ...
private boolean valid;
// ...
public void updateValid() {
// Check list is valid...
valid = true; // Updates `valid`
}
}
然而,由此导致group.getTiles().add(new Tile());
group.updateValid();
字段可能与列表不一致(例如,如果在添加/删除元素后忘记调用valid
)。
我已经意识到一种更简单的方法就是让一个方法返回一个布尔值而不是更新一个布尔字段,但是我不确定这是否理想,因为它仍然可以用于列表处于无效状态。
答案 0 :(得分:2)
最安全的解决方案是公开控制对列表访问的各个方法,而不是暴露整个对象:
route.legs[route.legs.length-1].end_location.lat()
route.legs[route.legs.length-1].end_location.lng()
如果您的验证逻辑涉及列表中的其他元素,您可以在插入后计算它:
class Group {
private List<Tile> tiles;
public Group(List<Tile> tiles) {
// defensive copy
this.tiles = new LinkedList<>(tiles);
}
public Group() {
this.tiles = new LinkedList<>();
}
public boolean add(Tile tile) {
// validate *before* inserting
return validate(tile) && tiles.add(tile);
}
}
另一种方法是使用延迟验证,而不是期望客户端调用额外的方法:
public void add(Tile tile) {
tiles.add(tile);
updateValid(); // or throw IllegalStateException
}
根据您的读/写比率,这可能比您提出的急切验证更高或更低。
答案 1 :(得分:2)
updateValid()
方法最好验证添加/删除操作
要强制约束,此方法不应由类的客户端调用,如在您的用法示例中,而是由类的内部调用,即:修改List的任何Group方法都应调用私有updateValid()
方法点。
此外,boolean valid
字段的用处是什么?
如果验证失败,您是否应该停止处理并抛出异常?
否则,这意味着Group对象的当前状态可能不一致。这似乎是不可取的。
你可以这样做:
private void updateValid() {
if (...){ // is not valid
throw new IllegalArgumentException("modification not valid");
}
}
最后,正如shmosel所说,你还应该避免提供一个获得真实列表的公共方法。你可以做一个防御性的副本,以避免客户的变化:
public List<Tile> getTiles() {
return new LinkedList(tiles);
}