Подтвердить что ты не робот

Булевские ссылки равны нулю

Может ли кто-нибудь объяснить, почему этот код приводит к выходу ниже?

@Test
public void testBooleanArray() {
    Boolean[] ab = new Boolean[]{a, b};

    a = new Boolean(true);
    b = new Boolean(false);

    for(Boolean x : ab) {
        System.out.println(x);
    }
}

Результат:

null
null

Если массив ab не содержит указатели на объект a и объект b и поэтому выводит:

true
false
4b9b3361

Ответ 1

a = new Boolean(true);
b = new Boolean(false);

Это не изменяет объекты, на которые указывали a и b (элементы в массиве). Он указывает на объекты new.

Он не изменяет массив

Чтобы проиллюстрировать:

Boolean a = new Boolean(true);
Boolean b = new Boolean(false);
Boolean c = a;
Boolean d = b;
a = new Boolean(false);
b = new Boolean(true);

c и d будут по-прежнему истинными/ложными соответственно. Это то же самое, что происходит с массивом, за исключением того, что ссылка на массив не называется так же.

Ответ 2

Вы должны инициализировать свои логические элементы перед их назначением.

Boolean[] ab = new Boolean[]{a, b};

a = new Boolean(true);
b = new Boolean(false);

к

a = new Boolean(true);
b = new Boolean(false);

Boolean[] ab = new Boolean[]{a, b};

Это раньше с объектами, вы копируете ссылку на объект, а с помощью нового оператора вы создаете новый объект, первый a, b имеют значение null при назначении.

Ответ 3

Ваш код развернут:

Boolean a = null;
Boolean b = null;
Boolean[] ab = new Boolean[2];
ab[0] = a;
ab[1] = b;

a = new Boolean(true); 
b = new Boolean(false); 

В момент, когда содержимое переменных с именами a и b было скопировано в массив, было установлено значение null. Существует важная разница в копировании по значению и копировании по ссылке.

В качестве побочного примечания: рекомендуется использовать Boolean.TRUE вместо или, по крайней мере, Boolean.valueOf(true), чтобы избежать ненужного создания объекта. Существует не так много вариантов для логического значения, и логическое значение является неизменным.

Ответ 4

Я считаю полезным визуализировать элементы массива как указатели.

Сначала создаем два указателя, a и b, указывающие на нуль.

Boolean a = null, b = null;

Pointers a and b point to null

Затем мы создаем еще два указателя, ab[0] и ab[1], и указываем их на то же место, что и a и b. То есть null.

Boolean[] ab = new Boolean[]{a, b};

All four pointers point to null

Затем мы создаем новые объекты Boolean true и false (с частями инструкций new Boolean(true) и new Boolean(false)).

Two new Booleans have been created

Наконец, пусть a и b указывают на них.

a = new Boolean(true);
b = new Boolean(false);

a and b point to the new Booleans

Когда вы смотрите на это так, я думаю, что более понятно, почему изменение a и b не влияет на массив.

Ответ 5

... Это абсолютно нормально. Вы инициализируете значения, но, как правило, a и b все еще null, прежде чем процесс округляется до назначения переменных. Это не переменные, которые помещаются, а их значения или ссылки как элементы в массиве.

@Test
public void testBooleanArray() {
    /* We have a Boolean array, Boolean being able to hold a true, false but
    also a null as an object */
    Boolean[] ab = new Boolean[]{a, b}; /* We initialize the array with the variables
    here but ... */

    a = new Boolean(true); // ... the instances are only set at this stage
    b = new Boolean(false); /* Plus, even if Boolean is immutable, the use of new
    will actually create new objects */

    for(Boolean x : ab) {
        System.out.println(x);
    }
}