Почему ссылка Java не работает так, как ожидалось в этой Программе - PullRequest
2 голосов
/ 18 февраля 2010

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

package misc.matrix;

public class ReferenceTester {
    public static void main(String args[]){
        Boolean[][] input = { 
            {true  ,false ,true ,true ,false },
            {false ,true  ,true ,true ,true },
            {true  ,true  ,true ,true ,true },
            {true  ,true  ,true ,true ,true },
            {true  ,false ,true ,true ,true }
        };

        print(input);

        for(Boolean[] eachRow:input){
            for(Boolean eachVal:eachRow){
                eachVal = Boolean.TRUE;
            }
        }
        print(input);

        /*Expected output  
            true  true  true  true  true  
            true  true  true  true  true  
            true  true  true  true  true  
            true  true  true  true  true  
            true  true  true  true  true
        */
    }

    /**
     * Simply prints the array
     */
    private static void print(Boolean[][] input) {
        for(Boolean[] outArray:input){
            for(Boolean iVal:outArray){
                System.out.print(iVal?iVal+"  ":iVal+" ");
            }
            System.out.println();
        }
    }
}

Если вы посмотрите на вышеупомянутую программу, все, что я пытаюсь сделать, это изменить все значения в массиве на true и распечатать его. Но его просто печатает ввод снова. Может кто-нибудь, пожалуйста, скажите мне, почему это. Первоначально я использовал примитив логический в программе, но, поскольку я не хочу создавать копии, я использовал булевый класс-обертку, который является Java OBJECT, а не примитивами. (Разве каждый из них не является объектом JAVA!?!?!?!?) Почему это происходит на Java? Почему он не распечатал все значения, чтобы быть правдой?

Пожалуйста, сообщите.

Ответы [ 4 ]

6 голосов
/ 18 февраля 2010

Вы не можете изменять исходный объект внутри цикла foreach. Ваш цикл должен быть стандартным для цикла следующим образом:

for(int i = 0; i < input.length; i++){ 
    for(int j = 0; j < input[i].length; j++){ 
        input[i][j] = true; 
    } 
}

Редактировать: Если быть точным, eachVal в вашем цикле является указателем , а не ссылкой; следовательно, установка его для указания другого значения не меняет оригинал.

Точная форма, которую цикл foreach использует за кулисами, задается здесь , если вы хотите подтвердить это независимо.

2 голосов
/ 18 февраля 2010

Ваша проблема с циклом для изменения значения массива:

    for(Boolean[] eachRow:input){
        for(Boolean eachVal:eachRow){
            eachVal = Boolean.TRUE;
        }
    }

На каждой итерации переменная eachVal содержит ссылку на содержимое ячейки массива, как вы и ожидаете. Но проблема в том, что, поскольку Boolean является неизменяемым типом, то есть вы не можете изменить значение объекта Boolean после того, как он был создан - ваше назначение не работает. Фактически, то, что вы на самом деле делаете, это изменение объекта, на который указывает ссылка eachVal. То есть, поскольку eachVal является независимой переменной из input и eachRow, вы просто переназначаете эту переменную, не затрагивая содержимое массива.

Дайте мне знать, если вы хотите, чтобы я расширил или прояснил какой-то конкретный момент.

1 голос
/ 22 февраля 2010

То, что вы пытаетесь, аналогично следующему:

    int[] arr = { 1, 2, 3 };
    for (int i : arr) {
        i = 0;
    }

Это НЕ устанавливает все значения в массиве на 0. Java передает все по значению.

1 голос
/ 18 февраля 2010

@ mmyers получил ответ, вы попросили более подробную информацию, но я не смог уместить его в комментарии:

Таким образом, у вас есть массив ссылок на логические значения (это ВСЕГДА ссылки) и по вашему для каждогоВ цикле вы создаете ссылку, которая указывает на то же логическое значение, что и член этого массива.

Каждая итерация ссылки обновляется, чтобы указывать на то, на что указывает следующий указатель в массиве.

Когдавы используете equals, вы просто переназначаете ссылку, чтобы указать на что-то еще.

Если вы хотите обновить объект внутри вашего массива, он должен быть изменяемым (Boolean - нет), и вы должны иметьиспользовать мутатор вместо равных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...