简体   繁体   English

新关键字在Java中的作用

[英]Role of new keyword in Java

I am not sure how new keyword behaves in Java. 我不确定new关键字在Java中的表现如何。 Is it for sure that every time I will use new keyword, a new Object will be created on heap? 是否可以确保每次使用new关键字时,都会在堆上创建一个新的Object?

I got this doubt when I was studying following example- 当我在学习以下示例时,我对此产生了怀疑

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

The line Mixer m3 = new Mixer(m2); 线Mixer m3 = new Mixer(m2); invokes a constructor which does not create any new object. 调用不创建任何新对象的构造函数。 So, is it that no new object was created? 那么,是不是没有创建新对象?

Also, Which variable refers to which object in the end of program, ie till we get NullPointerExcetion for variable m5 . 另外,哪个变量引用程序末尾的哪个对象,即直到我们得到变量m5 NullPointerExcetion

Yes - every time you use new (as a keyword) a new object will be created. 是 - 每次使用new (作为关键字)时,都会创建一个新对象。 In this case: 在这种情况下:

Mixer m3 = new Mixer(m2);

The line Mixer m3 = new Mixer(m2); 线混合器m3 =新混合器(m2); invokes a constructor which does not create any new object. 调用不创建任何新对象的构造函数。

Your reasoning is completely incorrect. 你的推理是完全错误的。 A new Mixer is being created using m2 as a parameter. 正在使用m2作为参数创建新的Mixer Usually this indicates a copy constructor - creating a new Mixer with the same properties as the old one (but it is always a new, distinct object, and doesn't technically have to copy the properties of the object passed in at all.) 通常这表示一个复制构造函数 - 创建一个具有与旧属性相同的属性的新混合器(但它始终是一个新的,不同的对象,并且在技术上不必复制传入的对象的属性。)

new always creates a new instance (so always reserves heap memory, etc.). new总是创建一个新实例(所以总是保留堆内存等)。

This should illustrate it. 这应该说明一下。 note that == on an instance will tell you if it is the same instance (object) or a different one. 请注意,实例上的==将告诉您它是相同的实例(对象)还是不同的实例。 (which is why you should always use equals, unless this is what you want to do) (这就是为什么你应该总是使用equals,除非这是你想要做的)

I've added a funny thing happening with strings. 我添加了一个有趣的事情发生在字符串。 "abc" does not create a new instance, but reuses an existing one. “abc”不会创建新实例,但会重用现有实例。 but when you call new on the String class it does. 但是当你在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.");
        }

    }
}

From the programmer's perspective, new causes the creation of a new object. 从程序员的角度来看, new会导致创建一个新对象。

However, the compiler may perform escape analysis to determine whether the object really needs to be created on the heap at runtime. 但是,编译器可以执行转义分析以确定是否确实需要在运行时在堆上创建对象。

For your last question, your code creates two objects. 对于您的上一个问题,您的代码会创建两个对象。 One is referenced by m2, m3.m1 and m4, and the other is referenced by m3. 一个由m2,m3.m1和m4引用,另一个由m3引用。

First, forget about the stack/heap distinction - that is an implementation detail of the compiler or the runtime (depending on the language in question). 首先,忘记堆栈/堆的区别 - 这是编译器或运行时的实现细节(取决于所讨论的语言)。 It might make a difference if you are doing systems programming in C or assembly, but not when you are working in garbage-collected languages and environments like Java or .NET. 如果您使用C或汇编进行系统编程,那么它可能会有所不同,但是当您在垃圾收集语言和Java或.NET等环境中工作时,它可能会有所不同。

And to answer your question: new actually does two things in most(?) (all?) languages that has such an operator. 并回答你的问题: new实际上在大多数(?)(所有?)语言中都有两个具有这种运算符的语言。 It first allocates memory somewhere to hold an instance of the type, and then calls a constructor to initialize an instance of the type in that newly allocated memory. 它首先在某处分配内存以容纳该类型的实例,然后调用构造函数来初始化该新分配的内存中的该类型的实例。 Constructor chaining then may cause other constructors to be called (either on the same type, base classes/superclasses of the type, or anything that type's constructor needs to do its work). 然后构造函数链接可能会导致调用其他构造函数(在相同类型,类型的基类/超类或类型的构造函数需要执行其工作的任何内容上)。

As pointed out by @berry120 , a constructor taking a parameter of the same type as the type that the constructor is for usually indicates a copy constructor. 正如@ berry120所指出的,构造函数采用与构造函数类型相同类型的参数通常表示复制构造函数。 Another way of achieving the same result is to have and make an explicit call to something like a clone() method which returns a copy of the object it is called on. 实现相同结果的另一种方法是对clone()方法进行显式调用,该方法返回调用它的对象的副本。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM