Java 向类成员提供对其他类成员的引用
从安全编程实践的角度来看,从1到10的范围来看,以下情况有多糟糕?如果你发现它比5更糟糕,你会怎么做 我下面的目标是将B中地图列表中的数据转换成A。在这种情况下,对我来说,如果它是数据的副本或对原始数据的引用,就可以了。我发现下面的方法速度最快,但我有一种不舒服的感觉Java 向类成员提供对其他类成员的引用,java,oop,Java,Oop,从安全编程实践的角度来看,从1到10的范围来看,以下情况有多糟糕?如果你发现它比5更糟糕,你会怎么做 我下面的目标是将B中地图列表中的数据转换成A。在这种情况下,对我来说,如果它是数据的副本或对原始数据的引用,就可以了。我发现下面的方法速度最快,但我有一种不舒服的感觉 public class A { private List<Map<String, String>> _list = null; public A(B b) { _list
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;
}
}
公共A类{
私有列表_List=null;
公共服务A(B){
_list=b.getList();
}
}
公共B级{
私有列表_List=new ArrayList();
公共列表getList(){
//为了这个例子,在列表中放一些数据。。。
_添加(新的HashMap());
返回列表;
}
}
您所创建的只是对B.\u列表的引用。因此,如果你想复制这些项目,就需要10个。
您可以迭代所有b._列表项,并手动将它们添加到A._列表:
public A(B b) {
_list = new List<Map<String, String>> ();
for (Map<String,String> map : b.getList()) {
Map<String,String> newMap = new HashMap<String,String>();
while(map.keySet().iterator().hasNext()) {
String key = map.keySet().iterator().next();
newMap.put(key,map.get(key));
}
_list.add(newMap);
}
公共A(B){
_列表=新列表();
对于(映射:b.getList()){
Map newMap=newhashmap();
while(map.keySet().iterator().hasNext()){
String key=map.keySet().iterator().next();
newMap.put(key,map.get(key));
}
_list.add(newMap);
}
在这种情况下,对我来说,如果它是数据的副本或对原始数据的引用,那么就可以了
这是症结所在
传递对象实例是最快的,但允许调用方更改它,并使以后的更改可见(没有快照)
通常,这不是问题,因为调用方不是恶意的(但您可能希望防止编码错误)
如果您不希望调用方进行更改,可以将其包装为一个
如果需要快照,可以克隆列表
无论哪种方式,这都只会快照/保护列表本身,而不是它的单个元素。如果这些元素是可变的,同样的推理也适用。我想说,您也必须在效率和封装之间进行选择。通过直接访问类的成员,它的状态将发生更改。这可能是意外的,并导致n我还想说,它增加了两个类之间的耦合 另一种选择是让信息专家负责人来决定,并将工作交给掌握信息的班级。你将不得不判断本应在A班完成的工作是否真的是B班的责任
但事实上,速度和干净的代码可能是相互冲突的利益。有时,你只需要玩脏的游戏就可以足够快地完成它。潜在的问题有点复杂:
- 从安全角度来看,这是非常非常糟糕的
- 从性能角度来看,这非常非常好
- 从测试的角度来看,这是很好的,因为类中没有任何东西是您通过测试无法轻松访问的
- 从封装的角度来看,这是不好的,因为您公开了类的内部状态
- 从编码安全的角度来看,这是不好的,因为有人最终会滥用它来进行一些“整洁”的技巧,这将在其他地方导致奇怪的错误,而您将浪费大量时间来调试它
- 从API的角度来看,它可以是:很难想象一个API会变得更简单,但同时,它不能传达您的意图,如果您需要更改底层数据结构,事情就会严重破坏
- 尽可能多地使用不可变的。不可变的和值对象会被创建,并且在创建之后永远不会更改。除非创建非常昂贵,否则这些都是安全的,性能也可以。惰性创建在这里会有所帮助,但这通常是它自己的蠕虫。Guava提供了一套全面的集合,在创建之后无法更改创造 不要太依赖集合。不可修改*,因为支持集合仍然可以更改
- 使用写时复制数据结构。如果基础列表在A或B开始更改时立即克隆自身,则上述问题将消失。这将使每个列表都有自己的副本,从而有效地将它们彼此隔离。不幸的是,Java不支持这些内置结构
这个。列表表示对成员变量的访问。同时,使用单个字母作为类名和变量也会降低可读性。SomeClass
和其他类也会起作用。谢谢。我会调查我mmutable集合。我不知道存在这样的事情。问题:在B的getList()中创建(并因此返回)一个数据副本是否是一个充分的“防御”解决方案?usua