2013-06-05 9 views
5

newキーワードがJavaでどのように動作するかわかりません。 newキーワードを使用するたびに、新しいオブジェクトがヒープ上に作成されることを確認していますか?Javaでの新しいキーワードの役割

私は例 -

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);は、任意の新しいオブジェクトを作成しないコンストラクタを呼び出します。それで、新しいオブジェクトが作成されていませんか?

また、どの変数がプログラムの最後にどのオブジェクトを参照するか、つまり変数m5の場合はNullPointerExcetionになるまでです。

+1

なぜ新しいオブジェクトが作成されないと思いますか? –

+0

http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html –

+0

@ DaveNewton-新しいオブジェクトが作成された場合、どの変数がそのオブジェクトを参照していますか? –

答えて

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

    } 
} 
10

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

Mixer m3 = new Mixer(m2); 

インラインミキサーM3 =新しいミキサー(M2)。新しいオブジェクトを作成しないコンストラクタを呼び出します。

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

+1

m5は*がnullなのでNPEを引き起こします。 (m2.m1はnullに設定されています) – Fildor

+0

しかし、m2は「古い」ミキサーオブジェクトの参照変数であり、それはMixer構造体に渡されています。これは実際には "古い"ミキサーオブジェクトの新しい参照変数を作成していますか? –

+0

'm2'はヌルではありませんが、' m2'はパラメータなしで作成されるので、 'm1'フィールドはヌルです(これがNPE、' m2.m1'の原因です) – berry120

1

プログラマーの観点からは、newは新しいオブジェクトの作成を引き起こします。

ただし、コンパイラはescape analysisを実行して、実行時にオブジェクトを実際にヒープ上に作成する必要があるかどうかを判断できます。

あなたの最後の質問では、コードによって2つのオブジェクトが作成されます。 1つはm2、m3.m1とm4で参照され、もう1つはm3で参照されます。

+0

私はそれを知らなかった、ありがとう。 – Djon

1

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

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

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

0

新しいオブジェクトを作成し、そのコンストラクタに、既に作成した別のオブジェクトm2への参照が渡されます。

関連する問題