preface

The question of what exactly is the parameter passing between methods in Java, and why many people say that Java only has value passing, has always puzzled many people, even I have asked many experienced developers in the interview, they are also difficult to explain clearly.

I also wrote an article for a long time, I thought I made myself clear the matter, however, in this part of knowledge recently, I found that I was understood thoroughly enough, so I think through Google and see what other people understand, but unfortunately didn’t find good information clearly, so to speak.

So I decided to try to summarize the topic and re-understand the problem.

Rumours that time

This issue has been widely discussed on StackOverflow as well, and it seems that many programmers understand it differently, or even wrong. Others may know that parameter passing in Java is value passing, but can’t say why.

Before we dive into this, it’s worth correcting some of your previous misconceptions. If you have the following thoughts, then you need to read this article.

Error # 1: Value passing and reference passing are distinguished by what is passed. If it is a value, it is value passing. If it’s a reference, it’s reference-passing.


Myth # 2: Java is pass-by-reference.


Myth # 3: Passing a parameter of a normal type is a value pass, passing an object is a reference pass.

Real participation parameter

As we all know, you can define parameters when you define methods in Java. Public static void main(String[] args), where args is the argument. Parameters are divided into formal parameters and actual parameters in program language.

Formal arguments: Arguments used when defining the name and body of a function to receive arguments passed in when the function is called.


Actual arguments: When a function with arguments is called, there is a data passing relationship between the calling function and the called function. When a function is called in the calling function, the arguments in parentheses after the function name are called “actual arguments.”

Here’s a quick example:

public static void main(String[] args) {
  ParamTest pt = new ParamTest();
  pt.sout("Hollis"); Hollis} public void sout(String name) {// Name system.out.println (name); }Copy the code

The actual parameters are what is actually passed when a parameterized method is called, while the formal parameters are the parameters used to receive the contents of the arguments.

Evaluation strategy

We said that when we make a method call, we need to pass the actual parameter to the formal parameter, so what is passing in the process?

This is the concept of Evaluation Strategies in programming.

In computer science, an evaluation strategy is a set of (usually deterministic) rules that determine the evaluation of an expression in a programming language. The evaluation strategy defines when and in what order the actual parameters of a function are evaluated, when they are substituted into the function, and in what form the substitution takes place.

Evaluation strategies fall into two basic classes, strict and non-strict, based on how the actual parameters given to the function are handled.

Strict evaluation

In strict evaluation, the actual parameters given to a function are always evaluated before the function is applied during a function call. Most existing programming languages use strict evaluation of functions. Therefore, we will focus only on strict evaluation in this article.

There are several key evaluation strategies that we are concerned about in strict evaluation, namely Call by value, Call by Reference, and Call by sharing.

  • Value pass call (value pass)
    • In a call-by-value call, the actual argument is evaluated, and then its value is copied to the formal argument of the function being called. Since the formal argument gets only a “partial copy”, changing the value of the formal argument in the called function does not change the value of the actual argument.
  • Call by reference (application pass)
    • In a reference-by-reference call, the function is passed an implicit reference to its actual arguments rather than a copy of the arguments. Because a reference is passed, if the value of a formal parameter is changed in the called function, the change is visible to the caller.
  • Pass shared object call (shared object pass)
    • In the pass-shared object call, the address of the actual argument is obtained, then copied, and a copy of the address is passed to the formal argument of the called function. Since the address of the parameter refers to the same object, we call it “shared object”, so if the value of the formal parameter is changed in the called function, the caller can see the change.

I don’t know if you have noticed, in fact, the process of passing shared object call and passing value call is almost the same, they are “evaluated”, “copy”, “pass”. You taste, you fine taste.

However, the result of passing a shared object call is the same as that of passing a reference call. If the content of the argument is changed in the called function, the change will also affect the caller. You again taste, you again fine taste.

So what is the relationship between shared object passing and value passing and reference passing?

In this case, we should focus on the process, not the result, because the process of passing a shared object call is the same as that of passing a value call, and both have one key operation, “copy”. Therefore, we generally think of passing a shared object call as a special case of passing a value call

Leaving the pass shared object call aside, let’s review the main differences between the pass value call and the pass reference call:

Call-by-value refers to passing a copy of the actual argument to the function when it is called. Call-by-reference refers to passing a reference to the actual argument directly to the function when it is called.

Therefore, the main difference between the two is whether the transmission is direct or whether the transmission is a copy.

Here’s a visual example. To take a closer look at value calls and reference calls:

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.

Java evaluation strategy

We’ve looked at pass-by-value calls, pass-by-reference calls, and the special case of pass-by-value calls to shared objects. So what kind of evaluation strategy is used in Java?

A lot of people say that the basic data types in Java are passed by value, which is basically nothing to discuss, and it’s generally accepted.

However, many people mistake object passing in Java for reference passing. The main reason for this myth is that variables and objects in Java are referred to each other. In the Java language, objects are manipulated by reference to them. So, many people think of object passing as reference passing.

And many can cite the following code example:

public static void main(String[] args) {
      Test pt = new Test();
      User hollis = new User();
      hollis.setName("Hollis");
      hollis.setGender("Male");
      pt.pass(hollis);
      System.out.println("print in main , user is " + hollis);
    }
public void pass(User user) {
      user.setName("hollischuang");
      System.out.println("print in pass , user is " + user);
    }Copy the code

Output result:

print in pass , user is User{name='hollischuang', gender='Male'}
print in main , user is User{name='hollischuang', gender='Male'}Copy the code

As you can see, after the object type is passed to the Pass method, its contents change within the method, and eventually the object in the caller’s main method changes as well.

So, many people say that this is the same thing that happens with reference-passing: changing the value of a parameter within a method affects the caller.

But this is a mistake.

Object passing in Java

Many people use code examples to show that Java objects are passed by reference, so let’s start with the phenomenon and refute it.

As we said earlier, either value passing or reference passing is only one of the evaluation strategies, and there are many other evaluation strategies, such as the phenomenon of shared object passing mentioned earlier and reference passing are the same. Why does passing parameters in Java necessarily mean passing by reference and not passing shared objects?

So, what is the form of object passing in Java? In fact, it really is shared object passing.

This part of The Tutorials was explained in The Java™ Tutorials. First, the basic types are described as follows:

Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost.

That is, raw parameters are passed to methods by value. This means that any changes to parameter values exist only at the scope of the method. When the method returns, the parameters are gone, and any changes to them are lost.

Object passing is described as follows:

Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object’s fields can be changed in the method, if they have the proper access level.

That is, reference data type parameters (such as objects) are also passed to methods by value. This means that when the method returns, the reference passed in still refers to the same object as before. However, if the object fields have the appropriate access level, you can change the values of those fields in the method.

As the official documentation makes clear, Java is value passing, passing a reference to an object as a value to a method. You wonder, isn’t that shared object passing?

In fact, the evaluation strategy used in Java is called by shared object. That is, Java passes a copy of the object’s address to the formal arguments of the called function. It’s just that the term “pass-shared object calls” isn’t used very often, so people in the Java community often say “Java is pass-value calls, “which is true, because pass-shared object calls are a special case of pass-value calls.

Does the phenomenon of value passing conflict with shared object passing?

One of the questions many people might ask is, since shared object passing is a special case of value passing, why are their phenomena completely different?

Is it possible that if a value is changed in the called method during value passing, it will have an effect on the caller? So when does it matter and when does it not matter?

There is no conflict, and the confusion arises because people have a misunderstanding of what a change value is.

Let’s go back to the above example and see what actually happens during the call.

During parameter passing, the address 0X1213456 of the actual parameter is copied to the parameter. This process is essentially value passing, but the value passing is the application of the object.

So why does changing the value of a property in user have an effect on the original user?

In fact, the process is like this: you make a copy of your house key and give it to your friend. When he gets the key, he doesn’t make any changes to it. Instead, he uses the key to open the door of your house, enter the house, and smash your TV.

This process has no effect on the key in your hand, but the contents of the house corresponding to your key have been changed.

In other words, Java objects are passed by copying the reference relationship. If we find the address of the reference instead of changing the reference relationship, and change the contents of the reference, it will affect the caller, because we are pointing to the same shared object.

So, if we change the content of the pass method:

public void pass(User user) {
    user = new User();
    user.setName("hollischuang");
    System.out.println("print in pass , user is " + user);
}Copy the code

In the above code, we re-create a user object in the pass method and change its value. The output is as follows:

print in pass , user is User{name='hollischuang', gender='Male'}
print in main , user is User{name='Hollis', gender='Male'}Copy the code

Here’s what happened in the process:

This process is just like you copy a key and give it to your friend. After your friend gets the key you gave him, he finds a locksmith and modifies it. The key in his hand becomes the key to open his lock. At this time, he opens his house, even if the house is lit, your keys in hand, and your house has no effect.

So, object passing in Java does not have any effect on the original object if it is modifying a reference, but it does have an effect on the original object if it is directly modifying the value of a shared object’s property.

conclusion

As we know, in programming languages, parameters need to be passed between methods, and this passing strategy is called the evaluation strategy.

In programming, there are many kinds of evaluation strategies, the more common ones are value passing and reference passing. Another special case of value passing is shared object passing.

The biggest difference between value passing and reference passing is whether a copy is made. If a copy is passed, it is value passing; otherwise, it is reference passing.

In Java, parameter passing is implemented through value passing, but in the case of Java object passing, the content passed is a reference to the object.

We can conclude that the evaluation strategy in Java is shared object passing, which is perfectly correct.

But, just to make sense of what you’re saying, let’s say that in Java there’s only value passing, but the passing is a reference to an object. There’s nothing wrong with that.

However, you should never assume that reference passing exists in Java.

OK, that’s the end of this article. I wonder if this article has helped you solve the puzzle you’ve been wondering for a long time. Feel free to comment in the comments.

References:

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

https://en.wikipedia.org/wiki/Evaluation_strategy

https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

https://blog.penjee.com/passing-by-value-vs-by-reference-java-graphical/

Hollis, a person with a unique pursuit of Coding, is currently a technical expert of Alibaba, a personal technical blogger, and a co-author of “Three Courses for Programmers”, whose technical articles have been read by tens of millions online.

In this xiaobian to share some architecture actual combat project documents for free to everyone, in need of friends can come to get it!