java - 为类(class)成员提供对另一个类(class)成员的引用

标签 java oop

从一到十的等级,从安全编程实践的角度来看,以下情况有多糟糕?如果你发现它比五更糟糕,你会怎么做?

我下面的目标是将 B 中 map 列表中的数据获取到 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; 
    }
}

最佳答案

潜在的问题有点复杂:

  • 从安全角度来看,这非常非常糟糕。
  • 从性能的角度来看,这非常非常好。
  • 从测试的角度来看,这很好,因为类里面没有您无法通过测试轻松获得的内容
  • 从封装的角度来看,这很糟糕,因为您暴露了类的内部状态。
  • 从编码安全的角度来看,这很糟糕,因为有人最终会滥用它来实现一些“巧妙”的技巧,这会在其他地方导致奇怪的错误,而您将浪费大量时间来调试它。
  • 从 API 的角度来看,它可以是:很难想象 API 会更简单,但与此同时,它不会传达您的意图,如果您需要更改基础数据,事情就会严重崩溃结构。

在设计软件时,您需要牢记所有这些要点。随着时间的推移,您会感觉到自己犯了哪些错误以及如何避免这些错误。计算机既笨又慢,从来没有完美的解决方案。你可以努力让它在你写的时候尽可能地好。

如果您想进行防御性编码,您应该始终复制您获得或公开的任何数据。当然,如果“数据”是您的整个数据模型,那么您根本无法在每次调用方法时都复制所有内容。

这个死锁的解决方案:

  • 尽可能多地使用不可变对象(immutable对象)。不可变对象(immutable对象)和值对象被创建并且之后永远不会改变。这些总是安全的,除非创建非常昂贵,否则性能还可以。懒惰的创作在这里会有所帮助,但这通常是它自己的蠕虫 jar 头。 Guava 提供了一套全面的集合,创建后无法更改。

    不要过分依赖 Collections.unmodifiable*,因为后备集合仍然可以更改。

  • 使用写时复制数据结构。如果底层列表会在 A 或 B 开始更改它时立即克隆自身,那么上述问题就会消失。这将使每个副本都有自己的副本,从而有效地将它们彼此隔离开来。遗憾的是,Java 不支持这些内置功能。<​​/p>

关于java - 为类(class)成员提供对另一个类(class)成员的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8756085/

相关文章:

java - 为什么okhttp程序不会卡在while(true)中?

php - 两个交互类的 OOP 设计方法

java - 扩展可以是 has-a 关系吗?

java - 如何将变量参数传递给instanceof?

c# - IEnumerable<T> 如何在后台工作

java - 面向对象设计 : inheritance vs type (enum) variable

java - Java异常层次结构背后的基本原理

java - 按键监听器不工作

java - 在 Pivotal Cloud Foundry 上为 Spring Boot 应用程序外部化 Vault token /后端配置

java - Netbeans 我添加的库 JAR/文件夹在哪里