2015-08-07 4 views
1

Я пытался решить проблему, которая требует несколько методов:Попутный Ссылки на методы Java

IT выглядит как много, но вы действительно не нужно читать методы. Просто знайте, что я прохожу int[][] к методу, изменяя int[][] внутри метода, а затем проверяя на равенство int[][] вне метода.

public static boolean One(int[][] matrix){ 
    matrix = transpose(matrix); 
    matrix = reverseRow(matrix); 
    return Arrays.deepEquals(matrix, changed); 
} 
public static boolean Two(int[][] matrix){ 
    //180 degree clockwise 
    matrix = transpose(matrix); 
    matrix = reverseRow(matrix); 
    matrix = transpose(matrix); 
    matrix = reverseRow(matrix); 
    return Arrays.deepEquals(matrix,changed); 
} 
public static int[][] transpose(int[][] matrix){ 
    for(int i = 0; i < N; i++) { 
      for(int j = i+1; j < N; j++) { 
      int temp = matrix[i][j]; 
      matrix[i][j] = matrix[j][i]; 
      matrix[j][i] = temp; 
      } 
     } 
    return matrix; 
} 
public static int[][] reverseRow(int[][] matrix){ 
    for(int j = 0; j < N; j++){ 
     for(int i = 0; i < N/2; i++) { 
      int temp = matrix[j][i]; 
      matrix[j][i] = matrix[j][N - i - 1]; 
      matrix[j][N - i - 1] = temp; 
     } 
    } 
    return matrix; 
} 
public static int[][] reverseCol(int[][] matrix){ 
    for(int col = 0;col < matrix[0].length; col++){ 
     for(int row = 0; row < matrix.length/2; row++) { 
      int temp = matrix[row][col]; 
      matrix[row][col] = matrix[matrix.length - row - 1][col]; 
      matrix[matrix.length - row - 1][col] = temp; 
     } 
    } 
    return matrix;  
} 

Структура задача выглядит следующим образом: У меня есть Int [] [] оригинальных числа У меня есть Int [] [] числа, что является результатом преобразования оригинала номера. В частности, поворот на 90 градусов по часовой стрелке и поворот на 180 градусов по часовой стрелке.

Фактическая проблема намного больше, но я думаю, что существует правило против правильного ответа на проблемы, поэтому я сократил это до необходимого.

Проблема заключается в следующем: После запуска метода один исходный массив изменяется, поэтому он поврежден, прежде чем запускать метод два.

Например, Оригинал перед тем один метод:

1111 
0000 
0000 
0000 

Оригинал после метода One;

0001 
0001 
0001 
0001 

Эти изменения происходят сразу после запуска транспонирования (матрицы) и reverseRow (матрицы). Обратите внимание, что в режиме отладки java я могу видеть, что оригинал изменяется, когда я перехожу к этим методам. Я НЕ ДОЛЖЕН ПРИНИМАТЬ ОРИГИНАЛ. Я изменил переданную версию оригинала.

Так, 3 вопроса:

  1. Я думал, что объекты, передаваемые методы не изменятся, если не вернуть измененный объект и затем установите оригинал измененные в основном() или оригинальном методе ? Я не говорю о транспозиции или reverseRow, потому что они должны были менять матрицу внутри метода One.

  2. Я проверил это с помощью метода, использующего строки. Моя вера выше верна. Различаются ли int [] []?

  3. Как исправить это, чтобы исходный текст не изменился? Или я пропустил что-то действительно простое?

+2

@ MLProgrammer-CiM Вы имеете в виду пропускную стоимость. – Pshemo

+3

@ MLProgrammer-CiM Это Java, наши переменные содержат значения, которые являются ссылками на объекты. Когда мы передаем их методу, создаются новые ссылки, которые являются копиями исходных ссылок. – Pshemo

+2

@ MLProgrammer-CiM и из-за этого люди все еще смущены, когда мы пытаемся объяснить, что [Java - это пропускная способность (всегда)] (http://www.javaranch.com/campfire/StoryPassBy.jsp). – Pshemo

ответ

3

Это проще всего понять, когда вы узнаете, что переменные Java содержат ссылки, а не объекты.

И эти ссылки всегда передаются по значению, как обсуждалось в более раннем вопросе Is Java "pass-by-reference" or "pass-by-value"?.

Этот ответ касается ваших конкретных вопросов.

1) Я думал, что объекты, переданные методам, не будут изменены, если вы не вернете измененный объект, а затем установите оригинал в измененный в main() или исходный метод?

Объекты не передаются методам.Переменные Java: ссылки на объекты. Вы можете скопировать переменную java без копирования объекта.

Если вы передаете метод ссылочного типа методу, этот метод не может изменить вашу переменную. Однако он может изменять объект, на который ссылается переменная, если он изменен.

2) Я проверил это с помощью метода, использующего строки. Моя вера выше верна. Различаются ли int [] []?

Массив - это изменяемый объект, к которому вы обращаетесь через ссылку.

Строка - неизменный объект. Вероятно, вы пытаетесь изменить переменную вызывающего, назначив переменной вызываемого метода.

3) Как исправить это, чтобы исходный текст не изменился? Или я пропустил что-то действительно простое?

Вы можете сделать копию массива перед передачей ссылки на него методу.

Один из способов сделать это для одномерного массива - использовать System.arraycopy(). Ваш двухмерный массив построен из нескольких одномерных массивов, поэтому вы можете использовать несколько вызовов для System.arraycopy(), чтобы скопировать его.

Другие вопросы обсуждаются в этом вопросе: How do I copy a 2 Dimensional array in Java?. Обратите внимание, что принятый ответ в вопросе опускает необходимый шаг создания двумерного массива.

0

В Java все передано по значение. Однако запутанная вещь заключается в том, что это значение содержит исходный объект с номером.

Присвоение переменной изменяется только то, что ссылки входная переменная имеет:

void doSomething(String str){ 
    str = "New String"; // str variable now holds a reference to "New String" 
         // however, the original String Object was not changed 
} 

Однако это не изменения оригинальной строки. Фактически, String является неизменным объектом вместе со всеми примитивами int, double и т. Д. Это приводит меня к следующему утверждению:

Единственный способ изменить входной параметр вызывающей функции - вызвать метод этого параметр, который мутирует объект (например, param.setValue(newValue) или param[0] = newValue).

Это позволяет нам сделать пару замечаний:

  1. Примитивные типы (char, int, double и т.д.) не могут быть изменены в вызывающей функции, потому что они не содержат никаких методов мутировать данные.
  2. Неизменяемые объекты (String, Integer, Double и т. Д.) Никогда нельзя изменять в функции, поскольку по определению они не содержат методов, которые мутируют данные.
  3. Mutable Objects (StringBuilder, BigInteger, BigDecimal и т. Д.) Могут быть изменены только путем вызова методов мутатора на объекте (а не путем переназначения переменной).Для массивов вы можете думать о array[0] = newValue и т. Д., Как методы мутатора на Array, сродни list.set(0, newValue) для List.
+0

Обратите внимание, что переменные не указывают на ссылки. Вместо этого они * содержат * ссылки, указывающие на объекты. Кроме того, строки - это не примитивы, а неизменные объекты. –

+0

Спасибо, я внес изменения, чтобы исправить это. – bcorso

Смежные вопросы