0

I read a few articles and similar question in Stackoverflow; however, I did not quite get an answer to my question. Here is the code:

public class CoinFlipping {

    Random random = new Random();

    Boolean head = null;

    public void flip(Boolean b){
        b = random.nextBoolean();
    //      head = b; 
    }

    public static void main(String [] args){
        CoinFlipping cf = new CoinFlipping();
        cf.flip(cf.head);
        System.out.println("Head: "+cf.head);
    }

    }

I refer to this arcticle: Is Java "pass-by-reference" or "pass-by-value"? I can understand why that piece of code behaves as it does. When we call new dog() we basically create a new Dog object. I get it. However, the example that I provided seems to be confusing a bit. I am not creating an object in this case (aren't I?). I am changing a value. Then why in this case when I print results, I get null and not true or false?

Community
  • 1
  • 1
George Revkov
  • 95
  • 1
  • 8
  • `b = random.nextBoolean();` creates a new reference, so modifies the value of `b`, not the value referenced by `b`. – AntonH Jul 17 '14 at 17:18
  • @AntonH: b does not "reference a value." b _has_ a value which is a reference to an object (or a null reference). The assignment statement gives b a new value (i.e., a reference to a new object). – Solomon Slow Jul 17 '14 at 17:23
  • @jameslarge I was trying to simplify, so that OP would see what was wrong. But too much, apparently. – AntonH Jul 17 '14 at 17:28
  • there are answers on the linked question that directly address this. see http://stackoverflow.com/a/40507/217324 closing this as a duplicate. – Nathan Hughes Jul 17 '14 at 17:29
  • @AntonH Hello, so am I getting this right? When I pass any objects to methods, following happens: It looks up the value of the object through the reference, copies it and this copy is assigned to the local var (argument)? In this case I have another question. Is there any ways to pass a reference to method, so that I could take this reference, access the object and change it internal state? Is there a way to actually have a reference to an original object but not to copy inside of the method? – George Revkov Jul 17 '14 at 17:45
  • @George: not quite. it copies the reference (think reference = memory address) and passes *that* on. so the original reference can never change, what changes in the method is a separate pointer that was initialized using the reference originally, but now there's no connection. – Nathan Hughes Jul 17 '14 at 17:49
  • @NathanHughes Yes, I create a second reference to the same object, right? But I do not change the reference. I change the object that this reference is referring to. Am I wrong? I am not doing anything with reference b (not assigning to another object), I am trying to change the state of the object it is referring to. – George Revkov Jul 17 '14 at 17:57
  • @George: i think you are confused (which you say up front of course). if you can reword this to make your question more specific i'm ok with reopening. but in its present form i don't think this question is going to get you any better answers. and if you wanted to change the state of the object you would call b.something, that still works. the method is changing the reference to point to a different object. – Nathan Hughes Jul 17 '14 at 18:03
  • @NathanHughes actually, I think I get it. I am changing the local reference. Boolean is immutable so when I say ` b = random.nextBoolean();` I do not actually change original `head` value, right? I assign a new value (new object) to Boolean b. So, when I quit the method the original object is not changed and the one that was created has not reference (b is deleted), so it would be taken by a garbage collector. Am I right? If yes, in this case, I guess, there is not point to rename and reopen it. – George Revkov Jul 17 '14 at 18:12
  • @George: that sounds much better. your object's reference to head is unchanged by what goes on in the method, java is keeping that separate intentionally. – Nathan Hughes Jul 17 '14 at 18:16
  • All right, seems to be clear. I guess it was also a question of what is mutable and what is not. This article helped: http://www.javaranch.com/journal/2003/04/immutable.htm – George Revkov Jul 17 '14 at 18:18

2 Answers2

2

The parameter b is passed by value, even though b is itself a reference. Thus, when you call flip, the flip method treats b as a local variable that is a copy of what you pass into it. Changing this copy doesn't change cf.head.

If b were a reference to a mutable object, you could change the object b refers to, and that change would be seen by the rest of the program after flip returns. But a change to b itself is a change to a copy, and any such change will not be seen by the rest of the program. (Boolean is not mutable.)

ajb
  • 29,914
  • 3
  • 49
  • 73
1

To answer your question:

Then why in this case when I print results, I get null and not true or false?

I have created a step-by-step walktrough of your code to show you the pointers (references) of the specific variables and answer why it prints out null in the end:

1. Step: New CoinfFlipping object is created with default field values

CoinFlipping cf = new CoinFlipping();

Inside the CoinFlipping class:

Random random = new Random();
Boolean head = null;

cf ---- points to ----> CoinFlipping object
cf.random ---- points to ----> Random object
cf.head ---- points to ----> null


2. Step: Calling the flip method with cf.head as parameter on the cf object

cf.flip(cf.head);

When evoking this method, a variable b is created inside the scope of the flip method. The pointer (reference) from cf.head is copied into the variable b. So cf.head and b point then at the same thing.

public void flip(Boolean b){

cf ---- points to ----> CoinFlipping object
cf.random ---- points to ----> Random object
cf.head ---- points to ----> null
b ---- points to ----> null


3. Step: Inside the flip method b is being reassigned

b = random.nextBoolean();

cf ---- points to ----> CoinFlipping object
cf.random ---- points to ----> Random object
cf.head ---- points to ----> null
b ---- points to ----> a boolean value - either true or false


4. Step: Back in the main method to print out cf.head

System.out.println("Head: "+cf.head);

cf ---- points to ----> CoinFlipping object
cf.random ---- points to ----> Random object
cf.head ---- points to ----> null
b ---- points to ----> a boolean value - either true or false

As you can see, cf.head is still pointing to null, therefore null is being printed.

Solution:
To change this, you could let the method return a boolean value instead and assign that to cf.head in order to make cf.head point to a new boolean value.

Rika
  • 11
  • 3