为什么Java没有拷贝构造函数?
为什么Java不支持像C ++这样的拷贝构造函数?
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中,它只是复制引用 。 对象的状态不会被复制,所以隐式地调用复制构造器是没有意义的。
这就是所有这一切。
来自Bruce Eckel :
为什么[复制构造函数]在C ++而不是Java中工作?
复制构造函数是C ++的基本组成部分,因为它会自动生成一个对象的本地副本。 然而上面的例子certificate它不适用于Java。 为什么? 在Java中,我们操纵的所有东西都是一个句柄,而在C ++中,可以有类似句柄的实体,也可以直接传递对象。 这就是C ++的拷贝构造函数的用途:当你想要一个对象并通过值传递它,从而复制对象。 所以它在C ++中工作正常,但是你应该记住这个scheme在Java中失败,所以不要使用它。
(我build议阅读整个页面 – 实际上,从这里开始。)
我觉得这个答案很有意思。
首先,我相信在Java中所有的对象都在堆上,虽然你没有指针,但你有“引用”。 引用具有复制语义,Java在内部跟踪引用计数,以便其垃圾收集器知道什么是安全的摆脱。
由于只能通过可复制的引用来访问对象,所以需要复制对象的实际次数大大减less了(例如,在C ++中只是将一个对象传递给一个函数(通过值)会导致新的对象被复制构build只有对该对象的引用被传递)。 devise者可能认为clone()对剩下的用途就足够了。
这只是我的意见(我相信有一个合理的答案)
C ++中的复制构造函数在按值发送或返回类实例时非常有用,因为这是在透明地激活复制构造函数的时候。
由于在Java中所有的东西都是通过引用返回的,而且VM是面向dynamic分配的,所以复制构造函数的复杂性实际上是没有道理的。
另外,由于所有的事情都是经过参考的,开发者往往必须提供他们自己的实现和决定如何克隆字段。
猜猜他们认为你可以做一个clone()方法呢?
它有一种。 当浅拷贝是好的,你有[克隆()]( http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone()); ,当他们不是'你必须像C ++一样实现深层拷贝。
唯一的区别在于它是工厂方法而不是构造函数,但是在灵活性和可testing性方面,这可能是一件好事。
我不是一个C ++程序员,但我似乎记得有关“三个伙计” – 复制构造函数,赋值运算符和析构函数的规则。 如果你有一个,那么你可能需要三个。
所以也许没有语言中的析构函数,他们不想包含复制构造函数? 只是一个猜测。
那么可以。 它不会被隐式创build。 如果我不得不猜测,这可能与Java对象总是被堆分配的事实有关。
在C ++中,默认的拷贝构造函数是一个成员级的浅拷贝。 如果一个类拥有在堆上分配的内存(通过一个原始指针),这将导致该副本与原始内容共享,这不是你想要的。
想象一下,Java有这种行为。 任何具有对象字段的类(基本上都是这些对象)将会有错误的行为,您需要自己重写它。 对于99%的情况,你没有保存任何麻烦。 此外,你刚刚为自己创build了一个微妙的陷阱 – 想象你不小心忘记覆盖默认的复制构造函数。 如果它是默认生成的,并且您尝试使用它,那么编译器根本不会发出抱怨,但是您的程序在运行时将会出现错误。
即使他们做了一个默认的复制构造函数来执行深层复制,但我不确定这会特别有用。 不仅如此,您倾向于在Java中执行比C ++更less的副本,但是您并不总是希望深度复制一个字段。
你所拥有的对象,以及你持有的对象,因为你需要它们,但是不负责任,是相同的 – 只是字段。 所有权和借款不是一stream的概念。 对于你自己的对象,你想要深拷贝它们(除非它们是不可改变的,在这种情况下,你不应该打扰),而对于你刚刚持有引用的对象,你想复制引用。
我会争辩说,一个无意识地复制一切的拷贝构造函数也不适合于许多类。 当然,不仅仅是默认的浅拷贝。
Java 有复制构造函数
注意:除了演示d2 =新演示(d1) ,您可以编写演示d2 = d1
主要区别b / w二
演示d2 =新演示(d1)意味着新的对象被创build,并被分配内存但是
demo d2 = d1意味着只有引用variables被创build,它使用对象d1的相同的内存地址,因此d2没有分配独立的内存。
复制构造函数的语法:
看下面的例子第一个拷贝构造函数非常简单:))
classname(int datafield)//简单的构造函数
{
this.datafield =数据字段;
}
classname(类名对象)
{
datafield = object.datafield; //见下面的例子
}
现在拨打电话
{
classname obj = new classname();
classname anotherObject = obj; //或classname anotherObject = new classname(obj)
}
类演示 { 私人诠释长度; 私人广度; 私人诠释半径; demo(int x,int y) { 长度= X; 宽度= Y; } int area() { 返回长度*宽度; } //复制构造函数 演示(演示obj) { 长度= obj.length; 宽度= obj.breadth; } 公共静态无效的主要(string参数[]) { 演示d1 =新演示(5,6); 演示d2 =新演示(d1); / /调用复制build筑 System.out.println(“d1 object =”+ d1.area())的区域; System.out.println(“d2 object =”+ d2.area())的区域; } }