简体   繁体   中英

Could pass object as function parameter and reassign it in function to modify its value out of function scope in java?

I am confused about the pass-by-value mechanism in Java even though I have read some questions about it like this and this .

I thought primitive type is passed by value in function parameters so it won't change its value even though it is changed in the function scope.

public class A {
    void function(int i) {
        i = 3;
    }

    public static void main(String[] args) {
        int i = 2;
        function(i);
        System.out.println(i);  // variable `i` won't change
    }
}

But class object is passed by value of a reference in function parameters so it will change its value if it is changed in the function scope.

public class Obj{
    public double calPrice;
    public boolean isTop;
    public boolean isCate;
    public List<Integer> cList;
    public RPCRecord(double c, boolean iT, boolean iC, List<Integer> cL) {
        calPrice = c;
        isTop = iT;
        isCate = iC;
        cList = cL;
    }
}

void f2(Obj o) {
    List<Integer> l1 = new ArrayList<Integer>(){{
                        add(1);
                        add(2);
                        add(3);
                          }};
    Obj o2 = new Obj(10.0, true, false, l1);
    o = o2;
}

void f3(Obj obj) {
    obj.calPrice = 123123.1;
    obj.isTop = false;
    obj.add(10);
}

public class A {
    public static void main(String[] args) {
        Obj ojb = new Obj();
        f2(ojb);
        System.out.println(ojb);  // Object `obj` will change
        f3(ojb);
        System.out.println(ojb);  // Object `obj` will change
    }
}

Forgive that I am not familiar enough with the Java pass parameter mechanism.
Is that what I thought right?

While invoking a method with primitive types (byte, short, char, int, long, float, double, boolean) values are passed, with objects - references .

In other words, it's impossible to change the initial value of a primitive variable like int by passing it as an argument while calling a method. But it's doable with an object, but only in the case if it's a mutable object. For example, you can an instance of your custom class Obj or instance of StringBuilder , but you cant change a BigInteger or String , these classes are designed to be immutable.

https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

I think this is a common confusion over pass-by-value in Java.

If you want to think of it in terms of a rule: if you pass an object (reference) to a method, you cannot change which object is passed in. Put another way, you cannot change that reference to another object.

What you ARE able to do is change things WITHIN the object -- your f3 method above should change the things within the object passed to it just fine.

But you cannot -- as it appears you are trying to do in f2 -- change the object passed in (ojb in class A) to another object. To return an object from a method, it either has to be returned in the method's return statement, or it has to be a field in another object so that it can be changed within the other object.

Now, if you want the lower-level explanation, instead of the rule:

When you put an object variable name as a parameter to a method in Java, you are passing a 'pointer to' that object. You can think of it as the object being represented by its address in memory, and that you are passing a variable that holds that address. And you can think of the variable holding the address of the object as being passed by value, even though you are passing the OBJECT by reference.

The method gets the parameter as a special kind of variable, and can refer to that object with the parameter variable. And the method can change the variable; what it cannot do is change it for the caller.

Take your method from above:

void f2(Obj o) {
    List<Integer> l1 = new ArrayList<Integer>(){{
                        add(1);
                        add(2);
                        add(3);
                          }};
    Obj o2 = new Obj(10.0, true, false, l1);
    o = o2;
}

A caller passes in a parameter 'variable' containing a pointer to an object; the f2 method calls that parameter variable o . f2 can change the value of the parameter variable. But whatever object resided at that address still resides at that address, and any variables in the caller holding that address still hold that address.

Another way of looking at it: let's say the caller passes in a variable called george to your f2 method:

SomeObject george = new SomeObject();
f2(george);

and let's say that george is at address 1234. We could then think of o in f2 as holding 1234, the address of george . f2 creates a new object with Obj o2 = new Obj(10.0, true, false, l1); , let's say o2 is at address 5678. What the statement o = o2 in your f2 does is assign 5678 to o , replacing the 1234 that used to be there. This does not affect the caller; george is still at 1234. f2 changed a variable holding george 's address, but the caller doesn't have a way to know that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM