为什么Java没有复制构造函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/827785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why doesn't Java have a copy constructor?
提问by Cuga
Why doesn't Java support a copy constructor like in C++?
为什么 Java 不支持像 C++ 中的复制构造函数?
采纳答案by cletus
Java does. They're just not called implicitly like they are in C++ and I suspect that's your real question.
爪哇。它们只是不像在 C++ 中那样被隐式调用,我怀疑这是你真正的问题。
Firstly, a copy constructor is nothing more than:
首先,复制构造函数无非是:
public class Blah {
private int foo;
public Blah() { } // public no-args constructor
public Blah(Blah b) { foo = b.foo; } // copy constructor
}
Now C++ will implicitly call the copy constructor with a statement like this:
现在 C++ 将使用如下语句隐式调用复制构造函数:
Blah b2 = b1;
Cloning/copying in that instance simply makes no sense in Java because all b1 and b2 are references and not value objects like they are in C++. In C++ that statement makes a copy of the object's state. In Java it simply copies the reference. The object's state is not copied so implicitly calling the copy constructor makes no sense.
在该实例中克隆/复制在 Java 中根本没有意义,因为所有 b1 和 b2 都是引用,而不是像 C++ 中那样的值对象。在 C++ 中,该语句会复制对象的状态。在 Java 中,它只是简单地复制引用。对象的状态不会被复制,所以隐式调用复制构造函数是没有意义的。
And that's all there is to it really.
这就是它真正的全部内容。
回答by Ryan
Guess they figured you can just make a clone() method instead?
猜猜他们认为你可以只创建一个 clone() 方法?
回答by dicroce
I think the answer to this is very interesting.
我认为这个答案非常有趣。
For one, I believe that in Java all objects are on the heap, and while you don't have pointers, you do have "References". References have copy symantics and java internally keeps track of reference counts so that its garbage collector knows whats safe to get rid of.
一方面,我相信在 Java 中所有对象都在堆上,虽然您没有指针,但您确实有“引用”。引用具有复制语义,Java 内部会跟踪引用计数,以便其垃圾收集器知道可以安全删除的内容。
Since you only access objects through copyable references, the actual number of times you need to copy an object is greatly reduced (for example, in C++ just passing an object to a function (by value) results in new objects being copy constructed, in Java only the reference to the object is passed). The designers probably figured that clone() would be enough for the remaining uses.
由于您仅通过可复制引用访问对象,因此您需要复制对象的实际次数大大减少(例如,在 C++ 中,仅将对象传递给函数(按值)会导致复制构造新对象,在 Java 中只传递对对象的引用)。设计者可能认为 clone() 足以用于其余用途。
回答by Uri
This is just my opinion (I am sure there is a justifiable answer)
这只是我的意见(我相信有一个合理的答案)
Copy constructors in C++ are primarily useful when you are sending or returning instances of classes by value, since that is when the copy constructor is transparently activated.
当您按值发送或返回类的实例时,C++ 中的复制构造函数主要有用,因为那时复制构造函数被透明激活。
Since in Java everything is returned by reference, and the VM is geared towards dynamic allocation, there really wasn't a justification for the complexities of a copy constructor.
由于在 Java 中一切都是通过引用返回的,并且 VM 面向动态分配,因此复制构造函数的复杂性确实没有理由。
In addition, since everything is by reference, a developer would often have to provide their own implementation and decision on how to clone fields.
此外,由于一切都是参考,开发人员通常必须提供他们自己的实现和关于如何克隆字段的决定。
回答by Aaron Maenpaa
It kind of does. When shallow copies are okay you have [clone()](http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone())and when they aren't you have to implement a deep copy just like C++.
它有点像。当浅拷贝没问题时,你有 [clone()]( http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone()),当它们不是时你必须像 C++ 一样实现深拷贝。
The only substantive difference is that it's a factory method rather than a constructor proper, but in terms of flexibility and testability that's probably a good thing.
唯一的实质性区别是它是一个工厂方法而不是一个适当的构造函数,但就灵活性和可测试性而言,这可能是一件好事。
回答by David Hodgson
I'm not much of a C++ programmer, but I do seem to remember a rule about the "three amigos" - copy constructor, assignment operator, and destructor. If you have one, then you likely need all three.
我不是一个 C++ 程序员,但我似乎记得关于“三个朋友”的规则——复制构造函数、赋值运算符和析构函数。如果您有一个,那么您可能需要所有三个。
So maybe without a destructor in the language, they didn't want to include a copy constructor? Just a guess.
所以也许语言中没有析构函数,他们不想包含复制构造函数?只是一个猜测。
回答by Dan Breslau
From Bruce Eckel:
从布鲁斯·埃克尔:
Why does [a copy constructor] work in C++ and not Java?
The copy constructor is a fundamental part of C++, since it automatically makes a local copy of an object. Yet the example above proves that it does not work for Java. Why? In Java everything that we manipulate is a handle, while in C++ you can have handle-like entities and you can also pass around the objects directly. That's what the C++ copy constructor is for: when you want to take an object and pass it in by value, thus duplicating the object. So it works fine in C++, but you should keep in mind that this scheme fails in Java, so don't use it.
为什么 [复制构造函数] 在 C++ 中工作而不是在 Java 中工作?
复制构造函数是 C++ 的基本部分,因为它会自动生成对象的本地副本。然而上面的例子证明它不适用于Java。为什么?在 Java 中,我们操作的一切都是句柄,而在 C++ 中,您可以拥有类似句柄的实体,也可以直接传递对象。这就是 C++ 复制构造函数的用途:当您想要获取一个对象并按值传递它时,从而复制该对象。所以它在 C++ 中工作正常,但你应该记住这个方案在 Java 中失败,所以不要使用它。
(I recommend reading the entire page -- actually, start hereinstead.)
(我建议阅读整个页面——实际上,从这里开始。)
回答by Isabella Engineer
Java havecopy Constructor
Note:Instead of demo d2=new demo(d1),you can write demo d2=d1
Main difference b/w two
demo d2=new demo(d1)means new object is created and it is
allocated memory But
demo d2=d1implies only reference variable is created
which uses the same memory address of object d1and hence d2not allocated
seperated memory.
Java有复制构造函数
注意:代替demo d2=new demo(d1),你可以写demo d2=d1
主要区别 b/w 两个
demo d2=new demo(d1)表示创建新对象并分配内存但是
演示d2=d1意味着只创建引用变量,它使用对象d1的相同内存地址,因此d2没有分配单独的内存。
Syntax of copy constructor:
See below Example first Copy constructor is very easy :))
classname(int datafield) //Simple Constructor
{
this.datafield=datafield;
}
classname(classname object)
{
datafield=object.datafield;//See below example
}
Now for Calling
{
复制构造函数的语法:
见下例第一个复制构造函数很简单:))
classname(int datafield) //Simple Constructor
{
this.datafield=datafield;
}
classname(classname object)
{
datafield=object.datafield;//见下面的例子
}
现在调用
{
classname obj=new classname();
classname anotherObject=obj;//or classname anotherObject=new classname(obj)
类名 obj=新类名();
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()); } }
回答by Kevin
Well, it can. It just doesn't get created implicitly. If I had to guess, it's probably related to the fact that Java objects are always heap-allocated.
嗯,它可以。它只是不会被隐式创建。如果我不得不猜测,这可能与 Java 对象总是堆分配的事实有关。
In C++, the default copy constructor is a member-wise shallow copy. If a class owns memory allocated on the heap (via a raw pointer), this will cause the copy to share internals with the original, which is not what you want.
在 C++ 中,默认的拷贝构造函数是一个成员方式的浅拷贝。如果一个类拥有在堆上分配的内存(通过原始指针),这将导致副本与原始共享内部结构,这不是您想要的。
Imagine for a moment that Java had this behavior. Any class that has fields that are objects (read: essentially all of them) would have the wrong behavior, and you'd need to override it yourself. For 99% of cases, you haven't saved anyone any trouble. Further, you've just created a subtle trap for yourself - imagine you accidentally forget to override the default copy constructor. If it was generated by default, and you try to use it, the compiler won't complain at all, but your program will misbehave at runtime.
想象一下 Java 有这种行为。任何具有对象字段的类(阅读:基本上所有这些)都会有错误的行为,您需要自己覆盖它。对于 99% 的情况,您没有为任何人省去任何麻烦。此外,您刚刚为自己创建了一个微妙的陷阱 - 想象一下您不小心忘记覆盖默认的复制构造函数。如果它是默认生成的,而您尝试使用它,编译器根本不会抱怨,但您的程序在运行时会出现异常行为。
Even if they made a default copy constructor that performs a deep copy, I'm not sure that would be particularly useful. Not only do you tend to perform fewer copies in Java than C++ anyway, but you don't always want to deep copy a field.
即使他们制作了一个执行深度复制的默认复制构造函数,我也不确定这会特别有用。无论如何,与 C++ 相比,您不仅倾向于在 Java 中执行更少的复制,而且您并不总是想要深度复制一个字段。
Objects that you just own, and objects that you hold references to because you need them, but aren't responsible for, are the same - just fields. Ownership and borrowing are not first class concepts. For objects you own, you'd want to deep copy them (unless they're immutable, in which case you shouldn't bother), and for objects you just hold a reference to, you want to copy the reference.
您只拥有的对象和您持有引用的对象,因为您需要它们但不负责它们,是相同的 - 只是字段。所有权和借款不是一流的概念。对于您拥有的对象,您希望对其进行深度复制(除非它们是不可变的,在这种情况下您不必费心),而对于您只持有引用的对象,您希望复制该引用。
I would argue that a copy constructor that just mindlessly deep-copies everything wouldn't be suitable for many classes, either. Certainly more than shallow-copying by default, though.
我会争辩说,一个只是盲目地深度复制所有内容的复制构造函数也不适合许多类。不过,当然不仅仅是默认情况下的浅复制。