new关键字在Java中的作用

new关键字在Java中的作用,java,Java,我不确定new关键字在Java中的行为。是否可以确定每次我使用new关键字时,都会在堆上创建一个新对象 当我学习下面的例子时,我产生了这种怀疑- class Mixer { Mixer() { } Mixer(Mixer m) { m1 = m; } Mixer m1; public static void main(String[] args) { Mixer m2 = new Mixer(); Mixer m3 = new Mixer(m2); // Does

我不确定
new
关键字在Java中的行为。是否可以确定每次我使用
new
关键字时,都会在堆上创建一个新对象

当我学习下面的例子时,我产生了这种怀疑-

class Mixer {
  Mixer() { }
  Mixer(Mixer m) { m1 = m; }
  Mixer m1;
  public static void main(String[] args) {
    Mixer m2 = new Mixer();
    Mixer m3 = new Mixer(m2); // Does it create any new mixer object?
    m3.go();
    Mixer m4 = m3.m1;          m4.go(); 
    Mixer m5 = m2.m1;          m5.go();
  }
  void go() { System.out.print("hi "); }
}
行<代码>混合器m3=新混合器(m2)调用不创建任何新对象的构造函数。那么,是不是没有创建新对象


此外,哪个变量指的是程序结束时的哪个对象,即直到变量
m5

得到
nullpointerexception
为止。是-每次使用
new
(作为关键字)时,都将创建一个新对象。在这种情况下:

Mixer m3 = new Mixer(m2);
生产线混合器m3=新混合器(m2);调用不创建任何新对象的构造函数


你的推理完全错误。正在使用
m2
作为参数创建一个新的
混合器。通常这表示一个复制构造函数-创建一个与旧混合器具有相同属性的新混合器(但它始终是一个新的、不同的对象,从技术上讲根本不需要复制传入的对象的属性。)

从程序员的角度来看,
新建
会导致创建一个新对象

但是,编译器可能会执行以下操作,以确定在运行时是否确实需要在堆上创建对象


对于最后一个问题,您的代码创建了两个对象。一个由m2、m3.m1和m4引用,另一个由m3引用。

首先,忘记堆栈/堆的区别-这是编译器或运行时的实现细节(取决于所讨论的语言)。如果您使用C或汇编语言进行系统编程,这可能会有所不同,但在Java或.NET之类的垃圾收集语言和环境中工作时,情况就不一样了

为了回答您的问题:
new
在大多数(?)(all?)语言中都有这样一个操作符,它实际上做了两件事。它首先将内存分配到某个位置以保存该类型的实例,然后调用构造函数在新分配的内存中初始化该类型的实例。然后,构造函数链接可能会导致调用其他构造函数(在同一类型、该类型的基类/超类或该类型的构造函数需要执行其工作的任何对象上)


正如所指出的,采用与构造函数所针对的类型相同类型的参数的构造函数通常表示复制构造函数。实现相同结果的另一种方法是使用并显式调用类似于
clone()
的方法,该方法返回所调用对象的副本。

它确实创建了一个新对象,它的构造函数会被传递一个对您已经创建的另一个对象
m2
的引用。

new总是创建一个新实例(因此总是保留堆内存等)

这应该说明这一点。请注意,实例上的==将告诉您它是相同的实例(对象)还是不同的实例(对象)。(这就是为什么你应该总是使用equals,除非这是你想要做的)

我添加了一个关于字符串的有趣的事情。“abc”不会创建新实例,而是重用现有实例。但是当您在String类上调用new时,它会这样做

public class Test {
    private String value;

    public String getValue() {
        return value;
    }

    public Test() {
        value = "default";
    }
    public Test(Test t) {
        this.value = t.getValue();
    }

    public Test(String value) {
        this.value = value;
    }

    public static void main(String[] argv) {
        Test t1 = new Test();
        Test t2 = new Test(t1);

        if (t1 == t2) {
            System.out.println("t1 == t2. should not happen");
        } else {
            System.out.println("t1 is a different instance from t2");
        }

        String s1 = "test";
        String s2 = "test";

        if (s1 == s2) {
            System.out.println("s1 == s2. strings initialized with quotes don't always get a new instance.");
        } else {
            System.out.println("s1 is a different instance from s2. should not happen");
        }

        String s3 = new String("test");
        String s4 = new String(s3);

        if (s3 == s4) {
            System.out.println("s3 == s4. should not happen.");
        } else {
            System.out.println("s3 is a different instance from s4, as they were newed.");
        }

    }
}

是什么让你认为它没有创建新对象?@DaveNewton-如果创建了新对象,那么哪个变量引用了该对象?@Prateksingla在这种情况下,你将结果分配给--
m3
。@Prateksingla
m3
--还有什么可能?m5会导致NPE,因为它是空的。(设置为m2.m1,该值为null),但m2只是“旧”混合器对象的引用变量,它正在混合器构造中传递。这实际上是在为“旧”混合器对象创建一个新的引用变量,不是吗?
m2
不是空的-但是
m2
是在没有参数的情况下创建的,所以它的
m1
字段是空的(这就是导致NPE,
m2.m1
)与问题无关的原因,但是…,尽管它具有复制构造函数的形式,它不是以这种方式实施的。将旧对象设置为类变量,创建父子关系,而不是从一个对象复制到新对象。