为什么Java不支持C ++中的复制构造函数?
答案 0 :(得分:129)
Java确实如此。他们只是不像C ++那样被隐式调用,我怀疑这是你真正的问题。
首先,复制构造函数只不过是:
public class Blah {
private int foo;
public Blah() { } // public no-args constructor
public Blah(Blah b) { foo = b.foo; } // copy constructor
}
现在C ++将使用如下语句隐式调用复制构造函数:
Blah b2 = b1;
在该实例中克隆/复制在Java中没有任何意义,因为所有b1和b2都是引用而不是像C ++中那样的值对象。在C ++中,该语句复制了对象的状态。在Java中,它只是复制引用。不会复制对象的状态,因此隐式调用复制构造函数是没有意义的。
这就是真的。
答案 1 :(得分:13)
来自Bruce Eckel:
为什么[复制构造函数]在C ++而不是Java中工作?
复制构造函数是一个基础 C ++的一部分,因为它是自动的 制作对象的本地副本。然而 上面的例子证明了它的确如此 不适合Java。为什么?在Java中 我们操纵的一切都是 处理,而在C ++中你可以拥有 类似于句柄的实体,你也可以 直接绕过对象。 这就是C ++拷贝构造函数 适用于:当你想要一个 对象并通过值传递它,因此 复制对象。所以它有效 在C ++中很好,但你应该继续 请注意,此方案在Java中失败, 所以不要使用它。
(我建议您阅读整个页面 - 实际上,请改为启动here。)
答案 2 :(得分:9)
我认为答案非常有趣。
首先,我相信在Java中所有对象都在堆上,虽然你没有指针,但你确实有“引用”。引用具有复制语义,java在内部跟踪引用计数,以便其垃圾收集器知道什么是安全的。
由于您只通过可复制引用访问对象,因此大大减少了复制对象所需的实际次数(例如,在C ++中只是将对象传递给函数(按值)会导致新对象被复制构造,在Java中只传递对象的引用)。设计师可能认为clone()足以满足其余用途。
答案 3 :(得分:2)
这只是我的意见(我确信有合理的答案)
当您按值发送或返回类的实例时,C ++中的复制构造函数非常有用,因为这是透明激活复制构造函数的时候。
因为在Java中,所有东西都是通过引用返回的,而VM是面向动态分配的,所以复制构造函数的复杂性确实没有理由。
此外,由于所有内容都是通过引用,开发人员通常必须提供自己的实现和决定如何克隆字段。
答案 4 :(得分:1)
猜猜他们认为你可以改为制作一个clone()方法吗?
答案 5 :(得分:0)
有点像。当浅拷贝是可以的时候你有[clone()](http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone()),当它们不是你必须像C ++一样实现深拷贝时。
唯一的实质性区别是它是一种工厂方法而不是构造函数,但在灵活性和可测试性方面可能是一件好事。
答案 6 :(得分:0)
我不是一个C ++程序员,但我似乎记得关于“三个朋友”的规则 - 复制构造函数,赋值运算符和析构函数。如果你有一个,那么你可能需要这三个。
所以也许没有语言中的析构函数,他们不想包含复制构造函数?只是一个猜测。
答案 7 :(得分:0)
嗯,它可以。它没有隐含地创建。如果我不得不猜测,它可能与Java对象总是堆分配的事实有关。
在C ++中,默认的复制构造函数是一个成员浅的副本。如果一个类拥有在堆上分配的内存(通过原始指针),这将导致副本与原始内容共享内部,这不是您想要的。
想象一下Java有这种行为。任何具有对象字段的类(读取:基本上都是所有这些)都会有错误的行为,并且您需要自己覆盖它。对于99%的情况,您没有任何人遇到任何麻烦。此外,您刚刚为自己创建了一个微妙的陷阱 - 想象您不小心忘记覆盖默认的复制构造函数。如果它是默认生成的,并且您尝试使用它,编译器根本不会抱怨,但是您的程序在运行时会出错。
即使他们制作了执行深层复制的默认复制构造函数,我也不确定它会特别有用。不管怎样,你不仅倾向于用Java执行比C ++更少的副本,而且你也不总是希望深度复制字段。
你刚才拥有的对象,以及你所拥有的对象,因为你需要它们,但不负责,是相同的 - 只是字段。所有权和借款不是一流的概念。对于您拥有的对象,您需要深层复制它们(除非它们是不可变的,在这种情况下您不应该打扰),对于您只是持有引用的对象,您要复制它们参考。
我认为,复制构造函数只是盲目地复制所有内容,也不适用于许多类。当然,默认情况下不仅仅是浅层复制。
答案 8 :(得分:-1)
Java 拥有复制构造函数
注意:您可以编写 demo d2 = d1 ,而不是 demo d2 = new demo(d1)
主要差异b / w两个 demo d2 =新演示(d1)表示新对象已创建,它是
分配内存但是 demo d2 = d1 表示只创建了引用变量
使用相同的对象 d1 的内存地址,因此 d2 未分配
分离的记忆。
复制构造函数的语法:
见下文示例第一个复制构造函数非常简单:))
classname(int datafield)//简单构造函数
{
this.datafield =数据字段;
}
classname(classname object)
{
datafield = object.datafield; //见下面的例子
}
强>
现在来电话
{
classname obj = new classname();
classname anotherObject = obj; //或classname anotherObject = new classname(obj)
} 的
class demo { private int length; private int breadth; private int radius; demo(int x,int y) { length=x; breadth=y; } int area() { return length*breadth; } //Copy Constructor demo(demo obj) { length=obj.length; breadth=obj.breadth; } public static void main(String args[]) { demo d1=new demo(5,6); demo d2=new demo(d1);//Invokes Copy Constructure System.out.println("Area for d1 object="+d1.area()); System.out.println("Area for d2 object="+d2.area()); } }