为什么Java没有复制构造函数?

时间:2009-05-06 02:34:00

标签: java copy-constructor

为什么Java不支持C ++中的复制构造函数?

9 个答案:

答案 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());

    }
}