当前位置: 首页 > 知识库问答 >
问题:

Java 10工厂方法的复制适用于构造函数中的防御性复制吗

曾奇略
2023-03-14

当实现具有由给定给构造函数的集合初始化的聚合的不可变类时,构造函数必须生成集合的防御性副本,以防止调用方随后更改聚合。

在Java 10之前,这将导致如下代码:

class Thing
{
   private final List<Widget> widgets;

   public Thing(List<Widget> widgets) {
      this.widgets = Collections.unmodifiableList​(new ArrayList<>(widgets));
   }

   public List<Widget> getWidgets() {
      return widgets;
   }
}

Java 10添加了list.copyof()和friends,它们创建了给定集合的不可修改副本。这意味着对于Java 10+,我们可以编写如下代码:

class Thing
{
   private final List<Widget> widgets;

   public Thing(List<Widget> widgets) {
      this.widgets = List.copyOf(widgets);
   }

   public List<Widget> getWidgets() {
      return widgets;
   }
}

我说的对吗?

共有1个答案

谭学名
2023-03-14

令人沮丧的是,copyof的语义意味着它不适合在典型构造函数中创建防御性副本。问题是

如果给定的集合是不可修改的列表,则调用copyOf一般不会创建副本。

这意味着,如果给定的集合实际上是可修改的集合的不可修改的修饰符,则使用copyof不会提供防止对给定的集合进行后续修改的保护。以下代码将更改对象的聚合:

final List<Widget> widgets = new ArrayList<>();
widgets.add(widget1);
...
final Thing thing = new Thing(Collections.unmodifiableList(widgets));
...
widgets.add(widget2);
 类似资料:
  • 下面是关于Seth Ladd博客“Dart”中工厂构造器的使用-试图理解“工厂”构造器值。 在IMHO中,使用通用构造器,可以通过细微的差异实现相同的效果,但非常简单。 如上所示,尽管这两个实例 所以,我的问题是工厂构造函数(或工厂模式)比一般/const构造函数有什么特殊的优点?因为上面的示例代码本身并没有显示工厂构造函数的优点。 谁能解释一下在Dart语言而不是Java / C#中所谓的“工厂

  • 问题内容: python中是否有复制构造函数?如果没有,我将怎么做才能达到类似的目的? 情况是,我正在使用一个库,并且在其中扩展了其中一个类,并提供了额外的功能,我希望能够将从库中获得的对象转换为自己的类的实例。 问题答案: 我想你想要复制模块 您可以像控制泡菜一样控制复印。

  • copy constructor是一个构造函数,它通过使用先前创建的同一类的对象初始化它来创建对象。 复制构造函数用于 - 从另一个相同类型的对象初始化。 复制对象以将其作为参数传递给函数。 复制对象以从函数返回它。 如果没有在类中定义复制构造函数,则编译器本身定义一个。如果该类具有指针变量并具有一些动态内存分配,则必须具有复制构造函数。 这里显示了最常见的复制构造函数形式 - classname

  • 主要内容:默认拷贝构造函数拷贝和复制是一个意思,对应的英文单词都是 。 对于计算机来说,拷贝是指用一份原有的、已经存在的数据创建出一份新的数据,最终的结果是多了一份相同的数据。例如,将 Word 文档拷贝到U盘去复印店打印,将 D 盘的图片拷贝到桌面以方便浏览,将重要的文件上传到百度网盘以防止丢失等,都是「创建一份新数据」的意思。 在 C++ 中,拷贝并没有脱离它本来的含义,只是将这个含义进行了“特化”,是指用已经存在的对

  • 问题内容: 在有效的Java(第7章)中,它说 还要注意,我们没有使用Date的clone方法制作防御副本。由于Date是非最终的,因此不能保证clone方法返回一个类为java.util.Date的对象:它可能返回专门为恶意恶作剧而设计的不受信任子类的实例。这样的子类可以在创建实例时在私有静态列表中记录对每个实例的引用,并允许攻击者访问此列表。这将使攻击者可以在所有情况下自由支配。为防止此类攻击

  • 我在程序的某个部分遇到了问题,我将一个充当lambda函数的对象传递给另一个函数(我需要捕获一个常量this指针,这样我就不能使用实际的lambda)。这导致调用lambda的copy构造函数,该构造函数再次调用copy构造函数,最终堆栈溢出。我知道发生了什么,但我不知道复制构造函数为什么调用自己,也不知道如何解决这个问题。我复制了下面的问题。 编译器:MSVC 2010