Булевские ссылки равны нулю
Может ли кто-нибудь объяснить, почему этот код приводит к выходу ниже?
@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
Ответы
Ответ 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);
}
}