5

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);は、新しいオブジェクトを作成しないコンストラクターを呼び出します。では、新しいオブジェクトが作成されなかったということですか?

また、どの変数がプログラムの最後でどのオブジェクトを参照するか、つまりNullPointerExcetionvariable を取得するまでm5

4

5 に答える 5

10

newはい - (キーワードとして)を使用するたびに、新しいオブジェクトが作成されます。この場合:

Mixer m3 = new Mixer(m2);

行 Mixer m3 = new Mixer(m2); 新しいオブジェクトを作成しないコンストラクタを呼び出します。

あなたの推論は完全に間違っています。パラメータとして使用して、新しいMixerが作成されてm2います。通常、これはコピー コンストラクターを示します。つまり、古いミキサーと同じプロパティを持つ新しいミキサーを作成します (ただし、これは常に新しい別個のオブジェクトであり、渡されたオブジェクトのプロパティを技術的にコピーする必要はまったくありません)

于 2013-06-05T14:14:28.703 に答える
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.");
        }

    }
}
于 2013-06-05T14:39:54.277 に答える
1

プログラマの観点からnewは、新しいオブジェクトが作成されます。

ただし、コンパイラはエスケープ分析を実行して、実行時にオブジェクトをヒープ上に作成する必要があるかどうかを判断する場合があります。

最後の質問に対して、コードは 2 つのオブジェクトを作成します。1 つは m2、m3.m1、および m4 によって参照され、もう 1 つは m3 によって参照されます。

于 2013-06-05T14:19:58.353 に答える
1

まず、スタック/ヒープの区別を忘れてください。これは、コンパイラまたはランタイムの実装の詳細です (問題の言語によって異なります)。C やアセンブリでシステム プログラミングを行っている場合は違いが生じる可能性がありますが、Java や .NET などのガベージ コレクトされた言語や環境で作業している場合は違います。

そしてあなたの質問に答えるために:new実際には、そのような演算子を持つほとんどの(?)(すべての?)言語で2つのことを行います。まず、型のインスタンスを保持するためにどこかにメモリを割り当て、次にコンストラクタを呼び出して、新しく割り当てられたメモリ内の型のインスタンスを初期化します。コンストラクターの連鎖により、他のコンストラクターが呼び出される可能性があります (同じ型、型の基本クラス/スーパークラス、または型のコンストラクターが作業を行うために必要なもののいずれか)。

@ berry120が指摘したように、コンストラクターの対象となる型と同じ型のパラメーターを取るコンストラクターは、通常、コピー コンストラクターを示します。clone()同じ結果を達成する別の方法は、呼び出されたオブジェクトのコピーを返すメソッドのようなものを明示的に呼び出すことです。

于 2013-06-05T14:21:17.053 に答える