Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向类成员提供对其他类成员的引用_Java_Oop - Fatal编程技术网

Java 向类成员提供对其他类成员的引用

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

从安全编程实践的角度来看,从1到10的范围来看,以下情况有多糟糕?如果你发现它比5更糟糕,你会怎么做

我下面的目标是将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; 
    }
}
公共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不支持这些内置结构


谢谢。那会给我元素(地图)内容的副本吗在B的列表中?所以..这应该是复制技巧,希望我的编辑没有让你太迷惑Hanks。所以,如果我同意调用者更改数据,从而也影响B的内容,那么我的方法不会很可怕?不好的程度不到6级?在一个直接返回成员对象的类中有一个getter(即使不可变)是一种完全常见且被接受的模式。请确定它是否“可怕”,我们需要更多的上下文。就其本身而言,没有问题。使用“uu”作为私有变量的前缀已经过时。使用
这个。列表
表示对成员变量的访问。同时,使用单个字母作为类名和变量也会降低可读性。
SomeClass
其他类
也会起作用。谢谢。我会调查我mmutable集合。我不知道存在这样的事情。问题:在B的getList()中创建(并因此返回)一个数据副本是否是一个充分的“防御”解决方案?usua