Mateus Pires
Mateus Pires

Reputation: 983

Pass by value or reference

I know this subject is very beaten, but ...

I'm programming an app for android in java, but I come from c++ , where the question of value or reference is very explicit. The problem is:

Initially I have a class called Item that has a variable public int ID.

In a class called ListingItem, I have a static List list with two item added to it, each has assigned to its variable ID the value 1. In this class there is also a function public static List getList() that returns List, specifically, the List list of this class.

In another class, called Fragment, I have a List ItemList and a function private List getList() that returns List.

The getList() of Fragment class does the following:

private List <Item> getList()
{
    List<Item> list = ListingItem.getList() // copy list from ListingItem.list
    List<Item> returnList = new ArrayList<Item>();

    returnList.add(list.get(0);
    returnList.add(list.get(1); // copy to returnList two Item objects from list (that copied from ListingItem.list)

    returnList return;
}

Another function of class Fragment use Fragment.getList() like this:

private functionOfFragment()
{
    List<Item> ItemList = getList();

    itemList.get(0).ID = 2;
    itemList.get(1).ID = 2; // changing from 1 to 2
}

However, the value of ListingItem.list.get(0).ID and ListingItem.list.get(0).ID are also the value 2. How is this possible?

obs: THIS CODE IS ONLY REPRESENTATIVE, THE PROBLEM ISN'T THE SYNTAX ERROS!

Upvotes: 1

Views: 106

Answers (4)

Alexey A.
Alexey A.

Reputation: 1419

I would say in Java we "pass references by value", except primitives of course. In case of primitives they are itself passed by value.

Upvotes: 1

Radiodef
Radiodef

Reputation: 37845

Parameter passing by value in Java is not the same as in C++.

In Java:

  • Parameter passing is always by value.
  • An object reference is a variable itself, storing the location of an object.
  • Passing an object reference passes its value.

Therefore an object reference in Java is functionally like a pointer, but you cannot dereference and reassign it.

In C++ you can do this:

#include <iostream>

class SomeObj {
public:
    int num;
    SomeObj(int n) {
        num = n;
    }
};

void reassign(SomeObj* obj) {
    *obj = *(new SomeObj(5));
}

int main(int argc, char* const argv[]) {
    SomeObj* obj = new SomeObj(0);

    reassign(obj);

    // prints '5'
    std::cout << obj->num << std::endl;

    return 0;
}

You cannot do that in Java. A Java reference variable is not a C++ pointer, not a C++ reference and not a C++ object value.

You can only do this:

void reassignLocal(SomeObj* obj) {
    obj = new SomeObj(5);
}

And this:

void mutateElsewhere(SomeObj* obj) {
    obj->num = 5;
}

So creating a new List like the following:

static List<SomeObj> shallowCopy(List<SomeObj> input) {
    List<SomeObj> output = new ArrayList<SomeObj>(input.size());

    for (SomeObj obj : input)
        output.add(obj);

    return output;
}

Only copies the references from one list to the other. They are the same objects. Mutating output elements will mutate input elements and vice-versa. To change this you need to actually instantiate new objects.

static List<SomeObj> deepCopy(List<SomeObj> input) {
    List<SomeObj> output = new ArrayList<SomeObj>(input.size());

    for (SomeObj obj : input)
        output.add(new SomeObj(obj.num));

    return output;
}

Upvotes: 2

Vidya
Vidya

Reputation: 30310

In Java, pass by value vs. reference is very explicit too. There is only pass-by-value--for everything.

In your example, you retrieve Item instances from the ArrayList, and copies of the references are passed to returnList.add. Still, the copies point to the same objects in memory as the originals, and they all can be "dereferenced" with the dot operator.

That's what you are doing when you say itemList.get(1).ID = 2. Because ID is public, when you dereference, you are accessing the object and setting its value to something new.

So references to objects (and primitives too) are passed by value, but the objects they reference can be altered in the manner defined by the class API. That is not the same as pass-by-reference, which is not feasible in a language that manages memory.

Upvotes: 3

Elliott Frisch
Elliott Frisch

Reputation: 201447

Because the variables refer to the same referent. The value of every java.lang.Object (e.g. objects not primitives) variable is the reference address (e.g. the "confusing" default toString() implementation), I hope that helps! Also, this is backwards returnList return;.

Upvotes: 2

Related Questions