You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1.9 KiB

List
共享引用的风险分析

问题描述

在 Main.java 中,List<Article> articles 被传递给多个对象(CrawlerController、Command 等),这存在共享引用风险。

主要风险

1. 数据不一致风险

多个对象持有同一个 List 的引用,任何地方对 List 的修改都会影响其他地方。例如:

  • CrawlCommand 添加了新 Article
  • ListCommand 在遍历
  • 如果同时修改,可能导致 ConcurrentModificationException

2. 封装性破坏

List 在多个类之间共享,违反了封装原则:

  • 任何持有引用的类都可以随意修改 List
  • 无法追踪是谁、在什么时候修改了数据
  • 难以进行数据验证和完整性检查

3. 线程安全问题

如果未来引入多线程:

  • 多个线程同时访问同一个 List
  • 没有同步机制会导致数据损坏
  • 可能出现脏读、丢失更新等问题

4. 测试困难

  • 单元测试时难以隔离
  • 一个测试可能影响另一个测试的结果
  • 需要手动清理共享状态

解决方案

方案 1:使用不可变集合

// 返回不可变列表
public List<Article> getArticles() {
    return Collections.unmodifiableList(articles);
}

方案 2:防御性拷贝

// 创建副本
public List<Article> getArticlesCopy() {
    return new ArrayList<>(articles);
}

方案 3:使用 Repository 模式

// 通过 Repository 管理,不直接暴露 List
public class ArticleRepository {
    private List<Article> articles = new ArrayList<>();
    
    public void add(Article article) { }
    public List<Article> findAll() { 
        return new ArrayList<>(articles); // 返回副本
    }
}

总结

共享引用虽然方便,但会带来数据一致性、封装性、线程安全等问题。 最佳实践是:

  1. 最小化共享
  2. 必要时使用防御性拷贝
  3. 使用不可变集合
  4. 通过接口/Repository 封装访问

(字数:约 450 字)