Boolean references are null
Asked Answered
I

5

13

Can anyone explain why this code results in the below output?

@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);
    }
}

Result:

null
null

Should the array ab not holds pointers to object a and object b, and therefore output:

true
false
Izzo answered 15/10, 2013 at 15:58 Comment(3)
Now the trick question is how come you can assign the variables without Java complaining they don't exist :p . P.S: Notice the @Test annotation.Pagoda
I left the declaration out for brevity - nothing interesting to see there!Izzo
Ah shame. I thought there was some "magic" induced by the test environment. Obviously not the case but seen stranger things :)Pagoda
M
21
a = new Boolean(true);
b = new Boolean(false);

This does not change the objects that a and b were pointing to(the elements in the array). It points them to new objects.

It is not modfying the array

To illustrate:

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 and d will still be true/false respectively. This is the same thing that is happening with the array, except your array reference isn't named the same way.

Machinery answered 15/10, 2013 at 15:59 Comment(7)
Buzz kill/correct wording time. The above code does change the object that a and b point to. It doesn't, however, change the objects that the array element references that were copied from a and b (null) are pointing to.Nguyetni
@SotiriosDelimanolis Was thinking about it a bit, and it was really just linguistic ambiguity(still better clarified than not). If I do a.change(), I could say: I changed the object that a points to. If I do a = new Object();, I could say: I changed the object that a points to. It's just that one is talking about the reference, and the other the object.Machinery
Good point. Also context matters. Boolean is immutable so we would have to be speaking about the reference.Nguyetni
@SotiriosDelimanolis Ah, but I was saying that we are not changing it, so there's no inconsistencies that would rule out that option. There still IS an object, and it makes perfect sense for me to say that you are not changing that object (rather required actually). In any case, it's semantics at this point, and at least it's unambiguous now. I just can't believe I got 13 votes for thisMachinery
Pass-by-value is an important concept of Java. People need to understand it correctly. And SO needs to reward good explanations like this one.Nguyetni
@SotiriosDelimanolis Makes sense. I came from VB when I started java where you specified ByVal or ByRef in parameters. It really confused me when my teacher said java was always pass-by-value, because I noticed pass-by-reference behaviour sometimes and not others. I eventually read an article that cleared everything up for me. it said: "Java is always pass-by-value, but in the case of an object, the value IS a reference". That has always helped me.Machinery
For clarification purposes, in situations like this it is better to say something like: I made a change to the object 'a' is pointing to vs. I made 'a' point to a different object. I think both of those statements are fairly unambiguous.Postnatal
L
8

You have to initialize your booleans before assigning them.

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

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

to

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

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

This is before with Objects, you copy the reference to the object, and with new statement, you create a new object, the first a,b were null when assigning.

Lynnelle answered 15/10, 2013 at 16:0 Comment(0)
S
6

Your code unrolled:

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); 

The moment the content of the variables named a and b was copied to the array, it was set to null. There is an important difference to copy by value and copy by reference.

As a side-note: it is recommended to use Boolean.TRUE instead or at least Boolean.valueOf(true), to avoid unnecessary object creation. There aren't that many options for a boolean value and Boolean is immutable.

Stavro answered 15/10, 2013 at 16:43 Comment(1)
+1 I like this. Skips passed some syntactic sugar, and shows how it's no different than the example in my answer.Machinery
B
4

I think it's helpful to visualize the array elements as pointers.

We first create two pointers, a and b, both pointing to null.

Boolean a = null, b = null;

Pointers a and b point to null

Next, we create two more pointers, ab[0] and ab[1], and point them at the same place as a and b. That is, null.

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

All four pointers point to null

Then, we create new Boolean true and false objects (with the new Boolean(true) and new Boolean(false) parts of the statements).

Two new Booleans have been created

Finally, we let a and b point to them.

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

a and b point to the new Booleans

When you look at it this way, I think it's more clear why changing a and b has no effect on the array.

Bifoliolate answered 16/10, 2013 at 1:35 Comment(1)
Nice illustration. You could get into training or teaching :)Pagoda
P
3

... Which is absolutely normal. You are initializing values but, sequentially speaking, a and b are still null before the process gets round to assigning the variables. It's not the variables that are being placed but their values or references as elements in an array.

@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);
    }
}   
Pagoda answered 15/10, 2013 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.