【问题标题】:Why Java does not provide a default copy constructor?为什么 Java 不提供默认的复制构造函数?
【发布时间】:2019-06-13 12:57:12
【问题描述】:

注意:我知道这个问题:Why doesn't Java have a copy constructor?。这个问题略有不同。

我知道下面的 sn-p 只会创建一个对某处存在的对象的新引用:

MyClass obj = new MyClass();
MyClass copy = obj;

但为什么 Java 在以下情况下不提供默认的复制构造函数:

MyClass obj = new MyClass();
MyClass copy = new MyClass(obj);

我相信隐式复制构造函数可以做与 C++ 类似的事情,即在每个成员上调用复制构造函数。这将导致对象的深拷贝,假设所有管理资源的类都正确实现了它们的拷贝构造函数。

添加这样的特性也应该是向后兼容的,因为现在第二个 sn-p 不会在没有明确的类复制构造函数的情况下编译。

所以,为了让我的问题更准确:

  • 是否有什么阻止 Java 创建隐式复制构造函数,它会调用所有成员的复制构造函数?
  • 现在添加隐式复制构造函数是否会破坏任何现有程序?

【问题讨论】:

  • @BladeMight - 正如 OP 所说,这个问题与那个不同。
  • @T.J.Crowder 但是这个问题还有其他答案,我认为可以解决 OP 的问题。
  • @T.J.Crowder 喜欢这个:stackoverflow.com/a/827821/5420570
  • @BladeMight - 我看不出这如何回答问题末尾的两个要点。 (请注意,我认为这个问题无论如何都是题外话......)

标签: java language-lawyer


【解决方案1】:

是否有什么阻止 Java 创建隐式复制构造函数,它会在所有成员上调用复制构造函数?

主要是因为这显然不是它应该做的。

在这种情况下,您可能想要一个深层副本;在这种情况下,也许你想要一个浅拷贝;也许您根本不希望在另一种情况下复制实例;也许您希望以这些方式混合复制特定类的字段。

此外,添加此构造函数是另一种方法:在方法数量很重要的环境中(例如 Android 的 64k Dex 限制),您需要为不需要的东西付费。

如果你需要它,最好让你这样做,通过明确说明。


但是是什么阻止 Java 拥有这个?

鉴于您可以手动定义复制构造函数,因此自动添加它们在技术上显然是可行的。

我认为你不能这样做的一个原因是没有语言机制可以“删除”你不想被复制的类的构造函数。

很容易表明您不需要默认 ctor:只需定义您自己的 ctor,并带有任何签名。但是你不能对默认的复制 ctor 做同样的事情:根据定义,复制 ctor 将永远只有签名 YourClass(YourClass instance);所以你不能要求,比如说,你定义一个抛出的显式复制ctor,因为你已经将编译时错误(不存在这样的ctor)更改为运行时错误(它存在,但抛出)。

所以你必须开始发明额外的机制来删除构造函数——比如一个特殊的注释。但这需要更改工具来支持它。

从绝对意义上说,这并非不可能 - 但需要大量工作来更改语言以添加可以在现有语言中实现的功能。

【讨论】:

  • 我假设如果有人出于某种原因需要成员的浅表副本,这将是编写自己的复制构造函数实现的正当理由。但是关于方法限制的观点是非常合理的,我不知道这种限制的存在。谢谢。
  • Java doesn't need it,它不是免费的(这可能会破坏对它不免费的敏感内容)。这些确实是不提供它的充分理由。
  • @Yksisarvinen 关键不是你不能覆盖默认为深拷贝的拷贝构造函数;我质疑这是否是正确的默认值。我对 Google 的代码进行了一些分析,发现具有复制构造函数的类的数量很少——非常少——很好不到 1%。虽然这只是一个代码库,它可能具有特定的风格原因,因为它是如此之低(例如,这包括生成的类,如 protos,它们没有复制 ctor),但它仍然表明默认情况下拥有复制构​​造函数缺乏价值,无论如何品种。
  • @Yksisarvinen(以及为永远不需要复制的类删除复制构造函数的不成比例的负担)。
  • @AndyTurner 然后,在一小部分具有复制构造函数的类中,有一些类不应该拥有它,最突出的是java.lang.String...跨度>
【解决方案2】:

但确实如此。它是名为clone() 的方法,在Object 类中实现。

所以你想要做的,可以通过以下方式实现:

MyClass obj = new MyClass(); 
MyClass copy = (MyClass) obj.clone();

【讨论】:

  • 您可能想要解决问题中的两个粗体、项目符号的问题。
  • 我不会说这是“隐含的”。它要求我们提供clone()方法的实现而不是复制构造函数,但实现几乎相同。
  • 您可能还想指出clone () 的问题,如 Effective Java 中所述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多