从1到10的等级,从安全编程实践的角度来看,以下有多糟糕?如果你发现它比五更糟糕,你会做什么呢?
下面我的目标是获得的地图列表中的数据在B插入A.在这种情况下,对我来说,这是确定的,如果它要么是一个数据的副本或原始数据的参考.我发现这种方法最快,但我对此感到不安.
public class A {
private List<Map<String, String>> _list = null;
public A(B b) {
_list = b.getList();
}
}
public class B {
private List<Map<String, String>> _list = new ArrayList<Map<String, String>>();
public List<Map<String, String>> getList() {
// Put some data in _list just for the sake of this example...
_list.add(new HashMap<String, String>());
return _list;
}
}
Run Code Online (Sandbox Code Playgroud)
潜在的问题有点复杂:
在设计软件时,您需要将所有这些要点放在脑海中.随着时间的推移,您将会感受到您所犯的错误以及如何避免错误.计算机像转储一样缓慢而且速度很慢,但从来没有一个完美的解决方案.您可以努力使它在您编写时尽可能好.
如果您想要进行防御性编码,则应始终复制您获得或公开的任何数据.当然,如果"数据"是您的整个数据模型,那么每次调用方法时都无法复制所有内容.
解决这个僵局的方法:
尽可能多地使用不可变量.创建了不可变项和值对象,之后永远不会更改.除非创建非常昂贵,否则它们总是安全且性能良好.懒惰的创造在这里会有所帮助,但这通常是它自己的蠕虫.Guava提供了一套全面的系列,在创建后无法更改.
不要太依赖,Collections.unmodifiable*
因为支持集合仍然可以改变.
使用写时复制数据结构.如果A或B开始更改它,基础列表将自行克隆,上述问题就会消失.这将使每个自己的副本有效地将它们彼此隔离.不幸的是,Java并不支持这些内置的.