【问题标题】:Defensive copying in terms of a reference parameter to a constructor根据构造函数的引用参数进行防御性复制
【发布时间】:2013-06-02 02:06:49
【问题描述】:

谁能告诉我什么是JAVA中类的构造函数的引用参数的防御性复制

非常感谢

【问题讨论】:

  • 您先尝试过 Google 还是这里的搜索工具?
  • 我猜你必须先告诉我们“构造函数的引用参数”是什么。
  • 我在谷歌上搜索过,但没有答案,这就是我想知道什么是“构造函数的引用参数”的地方
  • 你知道什么是“防御性副本”吗?
  • 是的,我知道什么是防御性复制。只是我不知道如何回答这个问题。

标签: java defensive-copy


【解决方案1】:

鉴于我可以从问题中提取的内容,我想问题可以总结如下......

让我们从这个开始:

class NotSafeAtAll
{
    private final List<X> list;

    public NotSafeAtAll(final List<X> list)
    {
        this.list = list;
    }
}

这个类有一个大问题:它复制列表reference作为它的成员字段。这意味着如果构造函数的调用者修改了这个列表,更改也会反映在NotSafeAtAll 实例中。

这就是“防御性复制”发挥作用的地方。考虑:

class ALittleMoreSafe
{
    private final List<X> list;

    public ALittleMoreSafe(final List<X> list)
    {
        this.list = new ArrayList<X>(list);
    }
}

现在,该类拥有自己的列表副本;如果调用者修改了它作为参数传递给构造函数的列表,ALittleMoreSafe 实例不会受到影响。

当然,故事并没有到此结束。现在考虑后一个类中有一个方法可以返回它作为参数接收到的列表:

class ALittleMoreSafe
{
    private final List<X> list;

    public ALittleMoreSafe(final List<X> list)
    {
        list = new ArrayList<X>(list);
    }

    public List<X> unsafeGetList()
    {
        return list;
    }
}

你输了!即使您的构造函数是安全的,事实是您将引用返回到您的内部列表;调用者可以通过这个引用修改列表。

在这里,防御性副本可以拯救你,但有一个更好的解决方案:确保你返回的列表是不可变的:

public List<X> safeGetList()
{
    return Collections.unmodifiableList(list);
}

调用者修改返回列表的任何尝试都将失败。

那么,故事结束了吗?

没有。

只有在所有X 实例都是不可变的情况下才能结束。不幸的是,非常经典且过度使用的 bean 模式无法保证这一点。但这是另一回事了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 2020-07-14
    • 1970-01-01
    • 2016-03-29
    • 2021-08-31
    • 2011-04-08
    相关资源
    最近更新 更多