1

I keep seeing this when researching Java arguments on the site but I believe I am misunderstanding it.

Question 1: Is Java "pass-by-reference" or "pass-by-value"?

Question 2: Does Java pass by reference?

People keep saying that in java reference types are passed by value, so that the reference itself isn't changed. And I believe my confusion comes from what the "references itself" is.

Originally I interpreted it to mean that what the argument was referring to, couldn't be changed or modified in any way, such as something being added to a list. Sadly this to some degree is wrong and has caused interesting results.

When I run the simple code below I get [test1, test2], so in my mind "the reference" list got changed.

import java.util.ArrayList;
import java.util.List;

public class HelloWorld {
    public static void main(String[] args)
    {
        List list = new ArrayList();
        list.add("test1");
        breakStuff(list);
        System.out.println(list.toString());
    }

    public static void breakStuff( List l ) {
        l.add("test2");
    }
}

With my current "idea" of what the people mean (answers to Question 1), they are wrong as things are changing. What am I not understanding or overlooking?

Are the people referring to the fact that you can modify the data the argument is referencing, but you can't change which "data/object" the argument is referring to?

Community
  • 1
  • 1
FreakyDan
  • 559
  • 1
  • 7
  • 24
  • 2
    You can change the object referenced, but not the reference. – Peter Lawrey Jul 14 '14 at 18:16
  • 3
    You can *mutate* an object, if it is mutable (and an `ArrayList` is mutable), but you cannot make the variable in the caller refer to a different `List`. The acid test for pass-by-reference is whether you can write a `swap(Object a, Object b)` method that will switch `a` and `b` around in the caller. By the way, you shouldn't use raw types `List` and `ArrayList`, but instead `List` and `ArrayList`. – David Conrad Jul 14 '14 at 18:22
  • 1
    This has ***got*** to be a duplicate!! 100 times over. – Hot Licks Jul 14 '14 at 18:28
  • A "reference", in Java, has a *specific* meaning, and is essentially the same as a "pointer" in C. References are what are passed in parameter lists. They cannot be changed by the callee in a way that would be visible to the caller (because they are passed "by value"). This is different from the use of the term "reference" in, say, a textbook, where the "reference" is essentially some external entity (another book, eg). – Hot Licks Jul 14 '14 at 18:35
  • @PeterLawrey Thank you for explaining both sides together. Originally when I read "You can change the object referenced" in the questions linked, I thought they were meaning changing which object is referenced, just to be told later in the answer I can't. Hopefully I can better understand the terminology now :) – FreakyDan Jul 14 '14 at 21:51

7 Answers7

2
public class HelloWorld {
    public static void main(String[] args)
    {
        List list = new ArrayList(); // here list is a "reference" to an "ArrayList" Object
        list.add("test1"); // adding data to the "Object" using the "reference"
        breakStuff(list); // passing the "reference-by-value"
        System.out.println(list.toString()); // printing
    }

    public static void breakStuff( List l ) { // getting the same reference as the original. So l==list is true.
        l.add("test2"); // adding to the same/original object because the reference is same.
l=null; // try this and see what happens. l will point to a "different" object i/e, null while list will be pointing to the original one.
    }
}
TheLostMind
  • 35,966
  • 12
  • 68
  • 104
1

Are the people referring to the fact that you can modify the data the argument is referencing, but you can't change which "data/object" the argument is referring to?

Yes, exactly. For example:

public class HelloWorld {
  public static void main(String[] args)
  {
    List list = new ArrayList();
    list.add("test1");
    breakStuff(list);
    System.out.println(list.toString());
  }

  public static void breakStuff( List l ) {
    l.add("test2");
    l = new ArrayList();
    l.add("foo");
  }
}

Does not change the original list to be a new list with a single element named foo. This is what it meant by that the reference is passed by value: if you make the value copy of the reference refer to a new object, the original reference still refers to the same, old object.

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • Thank you, the ambiguity of the original questions and answers misled me. Thank you for clearing that up :) – FreakyDan Jul 14 '14 at 18:14
0

It means

a = c ;
f(a) { a = b; }
// after we are out of f() here a == c

However

a.x = 0
f(a) { a.x = 1 }
// after we are out of f() here a.x == 1
Alexander Kulyakhtin
  • 47,782
  • 38
  • 107
  • 158
0

A reference points to an object.

You didn't change the reference but the object.

This would change the reference, but it won't change the variable list because the reference itself gets copied:

public static void breakStuff( List l ) {
        l = new ArrayList();
}
Jimmy T.
  • 4,033
  • 2
  • 22
  • 38
0

What this mean is that when you pass reference by value you can change its value and nothing will happen.

void passReferenceByValue(List list) {//Java code

    list = new ArrayList(); //We assign new value to reference
    list.add("reftByValue")'

}
void passReference(List* list) {//Non Java code

   list = new ArrayList(); //We assign new value to reference 
   list.add("reference")'
}

Wen we test it:

  void testPassing() {

    List start = null;

    passByValue(start);

    System.out.println("PassByValue: " + start);

    passReference(start);

    System.out.println("PassReference:" + start);
  }

The output:

PassByValue: null
PassByValue: {reference}

The reason of common misunderstanding is mutation of instance not change of the reference.

   void mutationTest(List list) {

         list.add("mutationOfList"); // In this case we mutate the object that reference point.
   }
0

The ArrayList object is actually on the heap. The ArrayList object always stays where it is on the heap.

Your reference "list" (of type List) is "pointing" to that object on the heap. Or said another way: "list" contains the memory address of that object!

When you pass that reference to another method - you are passing the location of that object on the heap. Or said another way: you are passing the address of the (stationary) object on the heap from one method to another method.

When the breakstuff method uses the "l" reference it will modify the object that "l" points at.

A stupid, but informing analogy: You aim a magic rifle at a red deer on the hill beside your house. You then post the rifle to a friend in the next town. When the friend looks through the rifle sight the rifle immediately turns and points to the hill with the that red deer.

jpd
  • 683
  • 5
  • 8
0

Are you familiar with another language? A comparison would be instructive.

Java code:

public class HelloWorld {
    public static void main(String[] args)
    {
        List list = new ArrayList();
        list.add("test1");
        breakStuff(list);
        System.out.println(list.toString());
    }

    public static void breakStuff( List l ) {
        l.add("test2");
    }
}

equivalent C++:

class HelloWorld {
public:
    static void main(String[] args)
    {
        List *list = new ArrayList();
        list->add("test1");
        breakStuff(list);
        System::out->println(list->toString());
    }

    static void breakStuff( List *l ) {
        l->add("test2");
    }
}

Would you say there is pass by reference here in the C++? Or all pass by value?

newacct
  • 119,665
  • 29
  • 163
  • 224