2016-08-24 6 views
0

私のJava初心者の質問に申し訳ありません。以下の割り当てはJava、クローン()の問題?

double[][] d = { { 1, 2, 3 }, { 4, 5, 6 }, { 1, 0, 1} }; 
    Matrix A = new Matrix(d); 
    Matrix B= new Matrix(3,3); 
    A.test(B); 
    B.print(); 

結果は驚くべきもので呼び出す

B = A 

に行われる方法テストインサイド以下のクラス

public class Matrix { 

    public final double[][] items; 
    private final int rows_count, columns_count; 

    public Matrix(final int rows_count_, final int columns_count_) { 
     rows_count = rows_count_; columns_count = columns_count_; 
     items = new double[rows_count][columns_count]; 
    } 

    public Matrix(final double[][] data) { 
      rows_count = data.length; 
      columns_count = data[0].length; 
      items = new double[rows_count][columns_count]; 
      for (int i = 0; i < rows_count; i++) 
        for (int j = 0; j < columns_count; j++) 
    } 

    public Matrix copy() { 
      Matrix AC = new Matrix(rows_count, columns_count); 
      for (int i = 0; i < rows_count; i++) 
        for (int j = 0; j < columns_count; j++) 
          AC.items[i][j] = items[i][j]; 
      return AC; 
    } 

    public Matrix clone() { return this.copy } 

    public void test (Matrix B)  { 
      B = this.clone(); 
      B.items[0][0] = 1; 
    } 

にあります。にもかかわらず、

B = this.clone() 

であり、得られるBマトリックスはゼロである。

0.0 0.0 0.0 
0.0 0.0 0.0 
0.0 0.0 0.0 

Bが(テストを書き換え:-)値によって渡されたかのように行列Bが正しく

1.0 0.0 0.0 
0.0 0.0 0.0 
0.0 0.0 0.0 

変更され

public void test (Matrix B)  { 
      B.items[0][0] = 1; 
    } 

ようにどこに問題がある)に見えますおそらく間違って書かれたコピー/クローンメソッド?どのように問題を解決し、割り当てを実行するB = A?ご協力いただきありがとうございます。

+0

'B'内部の ' test() 'は' Matrix'の新しいインスタンスに設定されます。元の行列は変更されません。 – Phylogenesis

+0

@ Phylogenesis:正しい割り当てを書くにはB = A? – justik

+0

あなたの呼び出しコードでは、 'B = A.copy();'を使います。インスタンスメソッド内でそれを実行しようとしないでください。 – Phylogenesis

答えて

1

問題は、cloneが新しいインスタンスを返し、それが変更されるということです。 BMatrixのインスタンスにはまったく触れません。関数のパラメータを代入すると、渡された変数は変更されず、関数が復帰するとすべての変更が失われます。関数外の変更をアーカイブするには、それを保持する変数ではなく、渡されたオブジェクトを変更する必要があります。

Bを変更するには、testメソッドをBを返すように変更してから、それを再割り当てしてください(無効にしてしまいます)。

copy関数を引数としてMatrixにすると、新しい日付で更新されます(新しいMatrixは作成されません)。古いcopyでも、新しいMatrixを作成して新しいcopyに渡すことで、この新しい関数を使用することができます。

編集:あなたのコメントについてC++とポインタに言及:C++(および他の多くの言語)では、関数へのポインタを渡すことができます。これを行うと、再割り当ては関数の外で渡された変数を実際に変更します。 Javaでは、これは(私が知る限り)このようにはできません。このトピックに関する詳細は、this question

+0

@ Leon:C++では、問題を解決するテスト(Matrix ** B)を書くことができます。 – justik

+0

@ Leon:ありがとうございました。 – justik

1

classclone()メソッドがあります。あなたはそれを無効にせずに使うことができます。それを使用できるようにするには、クラスimplementsCloneableを確認する必要があります。

+0

@ Lajos:エラー:未報告の例外CloneNotSupportedException;キャッチされるか、スローされると宣言されなければならない。\t B =(行列)(this.clone()); – justik

+0

@justik、MatrixクラスはCloneableを実装していますか?あなたが答えで読むことができるように、これは私の答えのためのperequisiteです。あなたのエラーは、MatrixがCloneableを実装することを忘れていたことを示しています(http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/CloneNotSupportedException.html) –

0

test()メソッドの問題は、オブジェクトを返さないため、メソッド外では何も変更しないことです。この場合

パブリックボイド試験(マトリックスB) Bがローカル変数であり、それは、その寿命がメソッドを起動して開始し、方法が終了するときに終了します。 JavaはCallByReferenceではなくCallByReferenceです。つまり、メソッド内で実際のオブジェクト参照を渡すのではなく、同じ値を持つ新しい参照をコピーのように渡すことを意味します。

B = this.clone()。 BにAのクローンを割り当てるという事実にもかかわらず、Bはこのメソッド内でしか使用できず、メソッドに渡されたBのインスタンスには影響しません。

B.items [0] [0] = 1; // Bの元のインスタンスではなく、Bの内部(ローカル)変数のみを変更しています.Bを返さないため、このメソッド内の変更はすべて廃止され、Bは破棄されます。

あなたはこのようにそれを設計する必要があり、あなたの方法を動作させるために:

Public Matrix test(Matrix B){ 
B = this.clone(); 
B.items[0][0] = 1; 
return B; 
} 

次に、あなたは、このように再びBに、このメソッドの呼び出しを割り当てる必要があります:

double[][] d = { {1,2,3},{4,5,6},{1,0,1}}; 
Matrix A = new Matrix(d); 
Matrix B = new Matrix(3,3); 
Matrix B = A.test(B); 
B.print();