2016-08-24 3 views
0

Извините за мой элементарный вопрос Java. Существует следующий классJava, clone() проблемы?

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 = A 

Вызов

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 = this.clone() 

Полученная матрица В имеет нули.

0.0 0.0 0.0 
0.0 0.0 0.0 
0.0 0.0 0.0 

Это выглядит так, как будто B передается по значению :-) Переписывая тест() так, как

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

матрица B модифицируется правильно

1.0 0.0 0.0 
0.0 0.0 0.0 
0.0 0.0 0.0 

Где проблема , возможно, неправильно написанный метод копирования/клонирования? Как исправить проблему и выполнить назначение B = A? Спасибо за вашу помощь.

+0

'' B' внутри test() 'установлен в новый экземпляр' Matrix'. Исходная матрица не изменяется. – Phylogenesis

+0

@ Филогенез: Как написать правильное назначение B = A? – justik

+0

В вашем кодовом коде используйте 'B = A.copy();'. Не пытайтесь делать это внутри метода экземпляра. – Phylogenesis

ответ

1

Проблема заключается в том, что clone возвращает новый экземпляр, который затем изменяется. Экземпляр Matrix в B не затрагивается вообще. Присвоение параметра функции новое значение не изменяет переданную переменную, и все изменения теряются после возвращения функции. Вы должны изменить переданный объект, а не переменную, удерживающую его, чтобы архивировать изменение вне функции.

Чтобы изменить B, вы можете либо изменить свой метод test, чтобы вернуть B, а затем вывести его наружу (что сделало бы передачу бесполезной).

Другим способом было бы сделать функцию copy с аргументом Matrix, который затем обновляет его с новой датой (без создания нового Matrix). Старый copy может затем использовать эту новую функцию, сначала создав новую матрицу, а затем передав ее новому copy.

Редактировать: О вашем комментарии, упоминающем C++ и указатели: на C++ (и на многих других языках) вы можете передать указатель на функцию. Если вы это сделаете, переопределение фактически изменяет переданную переменную вне функции. На Java это невозможно, насколько мне известно. Вы можете найти больше на эту тему в this question

+0

@ Leon: В C++ я могу написать тест (Matrix ** B), который решает проблему ... – justik

+0

@ Leon: Спасибо за вашу помощь. – justik

1

Существует clone() метод Objectclass. Вы можете использовать его, не переопределяя его. Чтобы иметь возможность использовать его, вам необходимо убедиться, что вы класс implementsCloneable.

public class Matrix implements Cloneable { 
    //... 
} 
+0

@ Lajos: Ошибка: незарегистрированное исключение CloneNotSupportedException; должен быть пойман или объявлен брошенным \t B = (Матрица) (this.clone()); – justik

+0

@justik, реализует ли ваш класс Matrix Cloneable? Это является ответом на мой ответ, который вы можете прочитать в ответе. В вашей ошибке указано, что вы забыли указать, что Matrix реализует Cloneable (http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/CloneNotSupportedException.html) –

0

Проблема с методом испытаний() является то, что он не возвращает какой-либо объект, таким образом, не делая никаких изменений за пределами метода.

общественного недействительный тест (Матрица Б) В в этом случае является локальным переменным, это означает, что его срок службы начинается с началом метода и заканчивается, когда метод завершаются. Java - это CallByValue, а не 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(); 
Смежные вопросы