Java为什么不支持C ++中的复制构造函数?
Java为什么不支持C ++中的复制构造函数?
Answers:
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中,它只是复制引用。对象的状态不会被复制,因此隐式调用复制构造函数没有任何意义。
这就是全部。
public class Blah { private A foo; //A is some class public Blah(Blah b) { foo = b.foo; } // this would not work would it ? }
public Blah(Blah b) { foo = new A(b.foo); }
从 Bruce Eckel:
为什么[复制构造函数]在C ++而不是Java中工作?
复制构造函数是C ++的基本组成部分,因为它会自动创建对象的本地副本。但是上面的示例证明了它不适用于Java。为什么?在Java中,我们操作的所有内容都是一个句柄,而在C ++中,您可以拥有类似句柄的实体,还可以直接传递对象。这就是C ++复制构造函数的目的:当您想要获取一个对象并按值传递它时,从而复制该对象。因此,它在C ++中可以正常工作,但是您应该记住,该方案在Java中会失败,因此请不要使用它。
(我建议阅读整个页面-实际上,请从此处开始。)
我认为答案很有趣。
首先,我相信在Java中所有对象都在堆上,虽然没有指针,但确实有“引用”。引用具有复制符号,并且Java在内部跟踪引用计数,以便其垃圾收集器知道可以安全删除的内容。
由于仅通过可复制的引用访问对象,因此大大减少了复制对象的实际次数(例如,在C ++中,仅将对象(按值)传递给函数会导致在Java中复制构造新对象。仅传递对对象的引用)。设计人员可能认为clone()对于其余用途就足够了。
Object.clone()
存在。我也+1
有点。如果可以使用浅表副本,则可以使用[clone()](http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone())而当它们不可用时,您必须像C ++一样实现深层副本。
唯一的实质区别是它是一种工厂方法,而不是适当的构造方法,但是就灵活性和可测试性而言,这可能是一件好事。
好吧,可以。只是不会隐式创建它。如果我不得不猜测,这可能与Java对象始终是堆分配的事实有关。
在C ++中,默认的副本构造函数是按成员的浅表副本。如果一个类拥有在堆上分配的内存(通过原始指针),这将导致副本与原始对象共享内部,这不是您想要的。
想象一下Java的行为。任何具有作为对象的字段的类(阅读:本质上都是它们)将具有错误的行为,并且您需要自己覆盖它。在99%的情况下,您没有为任何人省事。此外,您刚刚为自己创建了一个微妙的陷阱-想象一下您不小心忘记覆盖默认的副本构造函数。如果它是默认生成的,并且您尝试使用它,则编译器完全不会抱怨,但是您的程序在运行时会表现异常。
即使他们创建了执行深层复制的默认复制构造函数,但我不确定这样做是否特别有用。无论如何,您不仅会在Java中执行比C ++更少的副本,而且您并不总是希望深度复制一个字段。
您只是拥有的对象和由于需要但不负责的引用而持有的对象是相同的-只是字段。所有权和借款不是一流的概念。对于您拥有的对象,您想对其进行深层复制(除非它们是不可变的,在这种情况下您不应该打扰),而对于仅持有引用的对象,则需要复制该引用。
我会争辩说,一个复制构造函数,仅仅盲目地复制所有内容,也不适合许多类。当然,默认情况下,肯定比浅表复制要多。
Java具有副本构造函数
注意:代替demo d2 = new demo(d1),您可以编写demo d2 = d1
主要区别黑白两个
demo d2 = new demo(d1)意味着创建了新对象并为其分配了内存,但
demo d2 = d1 表示仅创建引用变量,该引用变量使用对象d1的相同内存地址,因此d2未分配单独的内存。
复制构造函数的语法:
参见下面的示例首先,复制构造函数非常简单:))
classname(int datafield)//简单的构造函数
{
this.datafield = datafield;
}
classname(类名对象)
{
datafield = object.datafield; //参见下面的示例
}
现在可以调用
{
classname obj = new classname();
classname anotherObject = obj; //或classname anotherObject = new classname(obj)
}
课堂示范 { 私有int长度; 私有int宽度; 私有整数半径; 演示(int x,int y) { 长度= x; 宽度= y; } int area() { 返回长度*宽度; } //复制构造函数 演示(演示obj) { 长度= obj.length; 广度= obj.breadth; } 公共静态void main(String args []) { demo d1 =新demo(5,6); demo d2 = new demo(d1); //调用复制结构 System.out.println(“ d1对象的面积=” + d1.area()); System.out.println(“ d2对象的面积=” + d2.area()); } }