新关键字在Java中的作用

时间:2013-06-05 14:14:01

标签: 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 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 "); }
}

Mixer m3 = new Mixer(m2);调用不创建任何新对象的构造函数。那么,是不是没有创建新对象?

此外,哪个变量引用程序末尾的哪个对象,即在变量NullPointerExcetion得到m5之前。

5 个答案:

答案 0 :(得分:10)

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

Mixer m3 = new Mixer(m2);
  

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

你的推理完全错误。正在使用Mixer作为参数创建新的m2。通常这表示一个复制构造函数 - 创建一个具有与旧属性相同的属性的新混合器(但它始终是一个新的,不同的对象,并且在技术上 没有复制对象的属性完全没过了。)

答案 1 :(得分:2)

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.");
        }

    }
}

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

首先,忘记堆栈/堆的区别 - 这是编译器或运行时的实现细节(取决于所讨论的语言)。如果您使用C或汇编进行系统编程,那么它可能会有所不同,但是当您使用垃圾收集语言和Java或.NET等环境时,它可能会有所不同。

回答你的问题:new实际上在大多数(?)(所有?)语言中有两个具有这种运算符的语言。它首先在某处分配内存以容纳该类型的实例,然后调用构造函数来初始化该新分配的内存中的该类型的实例。然后构造函数链接可能会导致调用其他构造函数(在相同类型,类型的基类/超类或类型构造函数需要执行其工作的任何内容上)。

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

答案 4 :(得分:0)

它会创建一个新对象,并且它的构造函数会传递对您已创建的另一个对象m2的引用。