1

Could somebody please explain how this program is executed?

Here is the code whose output I just can't quite seem to get it:

    class Box {
        int size;
        Box (int s) {
           size = s;
        }
    }
    public class Laser {
        public static void main(String[] args) {
            Box b1 = new Box(5);
            Box[] ba = go(b1, new Box(6));
            ba[0] = b1;
            for(Box b : ba)
                System.out.println(b.size + " ");
        }

        static Box[] go (Box b1, Box b2) {
            b1.size = 4;
            Box[] ma = {b2, b1};
            return ma;
        }
    }

The actual output when I run this is 4, 4. But according to my understanding this should be 5, 4. Can anyone please help understand how this is being executed?

Nunser
  • 4,512
  • 8
  • 25
  • 37

7 Answers7

3

I have added the comments for you;

The important TWIST that you missed here is;

Box[] ma = {b2, b1}; its not {b1,b2}. Memory locations are interchanged while returning.

       public static void main(String[] args) {
            Box b1 = new Box(5);                 // b1 == location A
            Box[] ba = go(b1, new Box(6));       // ba == location B which stores Location A, D

           // PLEASE NOTE HERE
           // After the function go() is executed;
           // ba[] will have {D, A}
           // So ba[0] will have object b1 which is at location A. 

            ba[0] = b1;                          // location B will now store A and A
            for(Box b : ba)
                System.out.println(b.size + " ");  //  Output: 4 and 4
        } 

        static Box[] go (Box b1, Box b2) {        // go(location A, location D )
            b1.size = 4;                          // A's object.size = 4
            Box[] ma = {b2, b1};                  // position is interchanged here (D and A)
            return ma;                            // return the location of ma
        }

Hope this helps.

Do let me know if you have any questions. Everything is pass by value in java. The memory addresses are passed by value.

JNL
  • 4,683
  • 18
  • 29
  • While you are correct, I believe he's asking why `ba[0]` isn't size=0, since he's using the `b1` object which has a declared size of 5 two lines prior. The key to that is the whole parameter-by-value paradigm that a bunch of other answers are poking at. – Deactivator2 Aug 13 '13 at 15:43
  • @Deactivator2 Yes I agree, it is definitely pass by value. – JNL Aug 13 '13 at 15:51
0

When you pass an object as a parameter, you're actually passing a copy of a reference to it. That is, if you modify the parameter object inside the method, the object will retain those modifications when that method returns, which is why you see b1 retaining the size = 4 assignment after go returns.

Deactivator2
  • 311
  • 1
  • 10
0

Java always passes references to objects in method calls. When you're calling go, the first argument (b1), is a reference to the same b1 Box that you have in your main. You then modify that object, whose size is now 4.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
0

The values passed to go are references to the objects. If you're coming from C, you can think of the parameters as having pointer types, something like

Box** go (Box *b1, Box *b2) {
     b1->size = 4;
     /* allocate an array of Box*, set it up, return it */
}

(Sorry if I got the C syntax wrong.) The pointers (references) themselves are passed by value, which means that if you say inside "go" (in the C program):

b1 = &some_other_box;

it doesn't affect any variables on the calling side, and it works the same way in Java. This makes it a bit different than a var parameter in PHP or Pascal.

ajb
  • 31,309
  • 3
  • 58
  • 84
0

Java passes copies of references to objects in method calls.

You can't change an object by assigning to it.

public static void main(String[] args) {
    Box b1 = new Box(5);
    Change(b1);
    System.out.println(b1.size + " ");

static void Change(Box b1) {
    b1 = new Box(6);
}

This will always return 5, because the function Change only overwrites the copy to the referenced object.

You can however affect the object's properties like so:

public static void main(String[] args) {
    Box b1 = new Box(5);
    Change(b1);
    System.out.println(b1.size + " ");

static void Change(Box b1) {
    b1.size = 6;
}

This will return 6 (the reference to the object remains unchanged).

bastos.sergio
  • 6,684
  • 4
  • 26
  • 36
0

If the function 'go' in the original post is in C (and b1 and b2 are C pointers), it can do the following two things (which the caller will see):

  1. Change the value of variables in the data structures pointed to by b1 and b2.
  2. Make the original b1 and b2 point to different data structures.

In Java, we can do 1 but NOT 2, since go does not have access to the original b1 and b2. (It has access to copies of b1 and b2. At the beginning of the subroutine, the copy b1 points to the same object as the original b1 and so on.)

Saying Java is pass by call DOES miss something, namely the ability of the function to do 1, i.e., change the properties of the object in the heap referenced by b1 and b2. [This is what happens in the statement, b1.size = 4;, which caused the original poster's confusion.]

b1 in 'go' is NOT the same location as b1 in 'main'. However, when the function starts, b1 in 'go' references the same object as b1 in 'main' and any changes made to the object using b1 in 'go' will be seen when b1 in 'main' is used as the reference.

However, if b1 in 'go' is set to another Box, b1 in 'main' will NOT see this; it will still see the previous Box.

V Chandrasekhar
  • 11
  • 1
  • 1
  • 4
-1

In Java, objects are passed by reference, primitives are passed by value.

public class Laser {
    public static void main(String[] args) {
        //Create a Box of size 5.
        Box b1 = new Box(5);
        //Create an array of Box objects, which are the results of the go method
        Box[] ba = go(b1, new Box(6));
        // ba now looks like {new Box(6), b1 /*b1 is size 4 now*/}
        // assign reference to b1 at index 0 in ba.
        ba[0] = b1;
        // array now looks like {b1, b1}
        for(Box b : ba)
            System.out.println(b.size + " ");
    }

    static Box[] go (Box b1, Box b2) {
        //set the size of the first box to 4
        b1.size = 4;
        //create an array of boxes, with b2 in index 0 and b1 in index 1
        Box[] ma = {b2, b1};
        return ma;
    }
}
codethulhu
  • 3,976
  • 2
  • 21
  • 15
  • 4
    Objects too are passed by value. – JNL Aug 13 '13 at 15:34
  • An object is a reference. And they are passed by value in Java. – c.s. Aug 13 '13 at 15:35
  • 3
    An object is not an object reference. An object is an object, and a reference is a reference. Method arguments are object references passed by value. – chrylis -cautiouslyoptimistic- Aug 13 '13 at 15:36
  • @chrylis is that an answer to my comment? Can you show me an example of where you can have access to an "object" (as you put it) and not just access to its reference? In Java all objects are references or pointers if you like – c.s. Aug 13 '13 at 15:56
  • @c.s. For wording, I would use: An object is a data structure that has state and behavior. In Java you can access an object through a reference. – Sotirios Delimanolis Aug 13 '13 at 20:10
  • 1
    @SotiriosDelimanolis agreed. In the specific context though talking about `Call by Reference` and `Call by Value` semantics (compare your definition of reference with this answer's first line: _"objects are passed by reference"_ to understand what I am talking about), objects behave like references (I would use the term pointers to be more clear) i.e. you can only indirectly access its memory. Anyway it all comes down to what the word "reference" means to each person :) – c.s. Aug 13 '13 at 20:24