This is the 7th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.

Today, I want to talk to you about the principle of parameter passing in Java. There are two kinds of parameter passing, value passing and reference passing.

Value passing: When a function is called, a copy of the actual parameter is passed to the function, so that the actual parameter is not affected if the parameter is modified.

Pass by reference: when a function is called, the address of the actual parameter is passed to the function, so that the modification of the parameter in the function will affect the actual parameter.

Primitive type passing

Let’s start with the most basic code:

@Test
public void test(a) {
    int n = 10;
    test01(n);
    System.out.println("Final result n==" + n);
}

private void test01(int m) {
    System.out.println("Before modification m==" + m);
    m = 20;
    System.out.println("After modification m==" + m);
}
Copy the code

Output result:

M == before modification10M == after modification20The final result n==10
Copy the code

If it’s not what you expect, then I don’t think you understand how parameter value passing and reference passing work.

Take a closer look at value passing and reference passing based on real-life scenarios:

You have a key, and if you just give your friend your key when he wants to go to your house, that’s pass-by. In that case, if he did something to the key, like he engraved his name on it, then when the key is returned to you, your key will have his engraved name on it.

You have a key, and when your friend wants to go to your house, you give him a duplicate key, and you still have your own key, and that’s value passing. In this case, what he does to the key doesn’t affect the key in your hand.

Let’s draw an example to better understand the above code:

When a function call occurs, n passes itself into test01, copies its value and assigns it to a new variable, m. As you can see, there is no relationship between n and M (m is just a copy of N), so changes to M do not affect N.

If you want to change the value of n, you can use the return value of the method:

n = test01(n);
Copy the code

Reference type passing

Let’s look at passing a reference type:

public class Dog {

    private String name;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString(a) {
        return "Dog{" +
                "name='" + name + '\' ' +
                '} '; }}@Test
public void test(a) {
    Dog dog1 = new Dog("White");
    test01(dog1);
    System.out.println("End result dog==" + dog1);
}

private void test01(Dog dog) {
    System.out.println("Before modification dog==" + dog);
    dog.setName("Black");
    System.out.println("After modification dog==" + dog);
}
Copy the code

Output result:

Before modification dog== dog {name='white'} dog== dog {name='black'} Dog1 ==Dog{name='black'}
Copy the code

To facilitate everyone’s understanding, or draw a picture to analyze:

In the test method we create an object called DOG1, which is stored in the heap at address 0x1120, so dog1 applies this address to the variable.

When we call test01, we create a variable dog on the stack. The dog variable is copied from dog1, so its heap memory is still 0x1120.

So when we modify the data using the dog variable, we’re essentially modifying the data in the same heap. Therefore, dog1, which originally referred to the memory address, can also see the corresponding change.

If you don’t understand the above, just remember the following two sentences:

When you pass data of a reference type, you pass not the reference itself, but the value; The value is just a memory address.

Because the same memory address is passed, operations on the data still affect the outside world.

Let’s look at the code below to see if this can change the value of the argument

@Test
public void test(a) {
    Dog dog1 = new Dog("White");
    test01(dog1);
    System.out.println("Final result dog1== + dog1);
}

private void test01(Dog dog) {
    System.out.println("Before modification dog==" + dog);
    dog = new Dog("Black");
    System.out.println("After modification dog==" + dog);
}
Copy the code

Output result:

Before modification dog== dog {name='white'} dog== dog {name='black'} Dog1 ==Dog{name='white'}
Copy the code

If Java is passed by reference, the final result should be printed black, which is still passed by value.

Or draw a picture to analyze it:

If passed by reference, the original 0x1120 should be replaced by the newly created 0x1121. In fact, as shown in the figure above, dog directly re-references an object dog = new dog (” little black “), and the two objects do not interfere with each other.

summary

Parameter passing in Java is actually value passing, but for reference type parameters, the content of the value is a reference to an object.