I want to make it clear to you thoroughly that Java is value passing and does not accept the kind of argument!

Foreword

Regarding what exactly is the parameter passing between methods in Java, why many people say that Java only has value passing, and so on, I have been puzzled by many people. Even when I interviewed many experienced developers during the interview, they are also very difficult. The explanation is clear.

I have also written an article for a long time, I thought I made this clear, but recently, when sorting out this part of knowledge, I found that I did n’t understand enough at the time, so I thought about reading it through Google See how other people understand, but unfortunately, no good information can be said clearly.

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

Rumors time

Regarding this issue, there has also been extensive discussion on StackOverflow. It seems that many programmers have different understandings of this issue, and even many people understand it wrong. Some people may know that parameter passing in Java is passing by value, but can't tell why.

Before starting an in-depth explanation, it is necessary to correct those previous misconceptions. If you have the following ideas, then you need to read this article.

Misunderstanding one: value transfer and reference transfer, the distinguishing condition is the content of the transfer, if it is a value, it is value transfer. If it is a reference, it is by reference.


Misunderstanding 2: Java is passing by reference.


Misunderstanding 3: If the passed parameter is a common type, it is passed by value, if it is an object, it is passed by reference.

Actual participation parameter

We all know that parameters can be defined when defining methods in Java. For example, the main method in Java, public static void main (String [] args), where args is the parameter. Parameters are divided into formal parameters and actual parameters in the programming language.

Formal parameters: the parameters used when defining the function name and function body, the purpose is to receive the parameters passed in when calling the function.


Actual parameters: When calling a parameterized function, there is a data transfer relationship between the calling function and the called function. When a function is called in the calling function, the parameter in parentheses after the function name is called the "actual parameter".

A simple 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);
}复制代码

The actual parameters are the content that is actually passed when the parameterized method is called, and the formal parameters are the parameters used to receive the actual parameter content.

Evaluation strategy

We said that when a method is called, the actual parameters need to be passed to the formal parameters, so what exactly is passed in the process of passing?

This is actually 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 expressions in programming languages. The evaluation strategy defines when and in what order the actual parameters of the function are evaluated, when they are substituted into the function, and in what form the substitution occurs.

Evaluation strategies are divided into two basic categories, based on how to deal with the actual parameters of the function, divided into strict and non-strict.

Strict evaluation

In "strict evaluation", during the function call, the actual parameters given to the function are always evaluated before applying the function. Most existing programming languages ​​use strict evaluation of functions. Therefore, we only focus on strict evaluation.

There are a few key evaluation strategy is that we are more concerned about the strict evaluation of that call-by (Call by value), call by reference (Call by reference) and pass the shared object calls (Call by sharing).

  • Call by value (value transfer)
    • In the pass-by-value call, the actual parameter is evaluated first, and then its value is copied to the formal parameter of the called function. Because the formal parameter is only a "local copy", so if the value of the formal parameter is changed in the called function, the actual parameter value will not be changed.
  • Call by reference (application pass)
    • In a pass-by-reference call, the implicit reference to its actual parameters is passed to the function rather than a copy of the actual parameters. Because the reference is passed, if the value of the formal parameter is changed in the called function, the change is visible to the caller.
  • Pass a shared object call (shared object transfer)
    • In a call to pass a shared object, first obtain the address of the actual parameter, then copy it, and pass the copy of the address to the formal parameter of the called function. Because the address of the parameter points to the same object, we call it "pass shared object", so if the value of the formal parameter is changed in the called function, the caller can see this change.

I don't know if you have found out, in fact, the process of calling shared objects and calling by value is almost the same. They are all "evaluation", "copy", and "pass". Your product, your product.

I want to make it clear to you thoroughly that Java is value passing and does not accept the kind of argument!

However, the result of the shared object call and the internal reference call are the same. If the content of the parameter is changed in the called function, then this change will also affect the caller. You taste again, you taste again.

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

For this problem, we should pay attention to the process, not the result, because the process of calling the shared object is the same as the process of calling by value, and there is a key operation, that is, "copy". Shared object call is a special case of call by value

Let's put the call to pass the shared object aside, let's review the main difference between the call by value and the call by reference:

Pass-by-value call refers to passing a copy of the actual parameter to the function when calling the function, and pass-by-reference call refers to passing the reference of the actual parameter to the function directly when calling the function.

I want to make it clear to you thoroughly that Java is value passing and does not accept the kind of argument!

Therefore, the main difference between the two is whether it is passed directly, or whether it is a copy.

Here we give an example of the image. Let's take a deeper understanding of pass-by-value calls and pass-by-reference calls:

You have a key. When your friend wants to go to your home, if you give him your key directly, this is reference passing.


In this case, if he did something to the key, for example, he engraved his name on the key, then when the key is returned to you, your own key will also have his engraved name on it.


You have a key. When your friend wants to go to your house, you engrave a new key to him, and your own is still in your hands. This is value transfer.


In this case, what he does with this key will not affect the key in your hand.

Java's evaluation strategy

Earlier, we introduced value-calling, reference-calling, and special cases of value-calling to pass shared object calls. So, which evaluation strategy is used in Java?

Many people say that the basic data types in Java are passed by value. There is basically nothing to discuss about this. It is generally believed that.

However, many people mistakenly believe that object passing in Java is passing by reference. The reason for this misunderstanding is mainly because there is a reference relationship between variables and objects in Java. Objects are manipulated by reference to objects in the Java language. Therefore, many people think that the transfer of objects is the transfer of references.

And many people can also cite the following code examples:

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);
    }复制代码

Output result:

print in pass , user is User{name='hollischuang', gender='Male'}
print in main , user is User{name='hollischuang', gender='Male'}复制代码

It can be seen that after the object type is passed to the pass method, its content is changed within the method, and finally the object in the caller's main method also changes.

Therefore, many people say that this is the same as passing by reference, that is, changing the value of a parameter within a method will affect the caller.

However, this is actually a misunderstanding.

Object passing in Java

Many people show that Java objects are passed by reference through the phenomenon of code examples, so we start with the phenomenon and refute this view first.

As we said earlier, whether it is value transfer or reference transfer is just one of the evaluation strategies. There are many evaluation strategies. For example, the phenomenon of shared object transfer mentioned above is the same as reference transfer. So why do you say that parameter passing in Java must be reference passing instead of shared object passing?

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

In fact, in "The Java ™ Tutorials", there is a description of this part of the content. 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, the original parameters are passed to the method by value. This means that any changes to the parameter values ​​will only exist within the scope of the method. When the method returns, the parameters will disappear and any changes to them will be lost.

The description of object transfer is 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.

In other words, reference data type parameters (such as objects) are also passed to the method by value. This means that when the method returns, the incoming reference still references the same object as before. However, if the object fields have the appropriate access level, you can change the values ​​of these fields in the method.

The official documentation of this point has made it very clear that Java is passing by value, just passing the reference of the object as a value to the method. Your details, isn't this shared object delivery?

In fact, the evaluation strategy used in Java is to pass the shared object call, that is to say, Java will pass a copy of the address of the object to the formal parameters of the called function. It's just that the word "passing shared object calls" is not commonly used, so people in the Java community usually say "Java is a call by value". That's right, because calling a shared object is actually a special case of call by value.

Does the phenomenon of value transfer and shared object transfer conflict?

Seeing here, many people may have a question. Since shared object transfer is a special case of value transfer, why are their phenomena completely different?

Is it possible to affect the caller if the value is changed in the called method during the value transfer? So when exactly will it affect and when will it not?

In fact, there is no conflict. The reason for this doubt is because everyone has a misunderstanding about what is "changing the value".

Let ’s go back to the example above and see what actually happened during the call?

I want to make it clear to you thoroughly that Java is value passing and does not accept the kind of argument!

In the process of parameter transmission, the actual parameter address 0X1213456 was copied to the formal parameter. This process is actually the transfer of value, but the content of the transfer is the application of the object.

So why did we change the value of the attribute in the user, but it had an effect on the original user?

In fact, the process is like this: you copied a key from your home to your friend. After he got the key, he did not make any changes to the key, but opened the room in your home through the key Door, enter the house and smash your TV.

This process has no effect on the key in your hand, but the content in the house corresponding to your key has been changed by someone.

In other words, the transfer of the Java object is to transfer the reference relationship by copying. If we do not change the reference relationship, but find the referenced address and change the content inside, it will affect the caller. Because everyone points 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);
}复制代码

In the above code, we renewed a user object in the pass method and changed his 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'}复制代码

Look at what happened in the whole process again:

I want to make it clear to you thoroughly that Java is value passing and does not accept the kind of argument!

This process is like if you copied a key to your friend, and after your friend got the key you gave him, find a locksmith to modify him, and the key in his hand became open. The key to his home lock. At this time, when he opened his house, even if he had ordered the house, it would have no effect on the keys in your hand and your house.

Therefore, object transfer in Java will not have any effect on the original object if it is modified by reference, but if the property value of the shared object is directly modified, it will affect the original object.

to sum up

We know that parameter passing between methods is required in a programming language. This passing strategy is called an evaluation strategy.

In program design, there are many evaluation strategies, the more common is value passing and reference passing. There is also a special case of value passing-shared object passing.

The biggest difference between value transfer and reference transfer is whether a copy is copied during the transfer. If the copy is transferred, it is value transfer, otherwise it is reference transfer.

In Java, in fact, the transfer of parameters is realized by value transfer, but for the transfer of Java objects, the content passed is a reference to the object.

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

However, in order for everyone to understand what you are saying, we say that in Java there is only value passing, but the content passed is a reference to the object. This is also fine.

However, you must not assume that there is reference passing in Java.

OK, the above is the whole content of this article, I don't know if this article helps you to solve the doubts you have always had in mind. Welcome to leave a message to talk about your thoughts.

Reference materials:

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/

Reprinted public number: Hollis, a person with a unique pursuit of Coding, currently an Alibaba technology expert, personal technology blogger, tens of millions of technical articles read on the whole network, co-author of "Three Courses for Programmers".


Guess you like

Origin juejin.im/post/5e9557ec51882573b4361126