Why only passed by value in Java?

For starters, in order to answer this question correctly, it is more difficult. When finishing the second day of the answer, I found that I could not even describe this thing is easy to understand simple language, unfortunately, I do not what this article can explain things in plain found online. So, there I write this in mind. In this article, I learned from what is actual parameter and formal parameter method begins, explain to you why Java only passed by value.

Rumor of time
on this issue, on StackOverflow had also led to extensive discussion, it appears that many programmers are not the same understanding of this problem, and even a lot of people understand is wrong. There are people who may know the parameters passed in Java are passed by value, but could not say why.

Before starting depth explanation, it is necessary to correct those errors before you view up. If you have the idea, then you need to take to read this article.

A misunderstanding: Condition value is passed and passed by reference, the distinction is content delivery, if it is a value, that value is passed. If a reference is passed by reference.

Understanding and error: Java is passed by reference.

Misunderstood Three: If the argument passed is a common type that is passed by value, and if the object that is passed by reference.

Real participation parameter
we all know, when the method is defined in Java can be defined parameters. For example, the main method in Java:

This is the inside of args parameter. Parameters are divided into formal and actual parameters in programming languages.

In the form of parameters: the parameter is used in the definition of the function names and function of the body when the object is used to receive incoming calls when the function parameters.

Actual parameters: calling the function with a time reference, the data transfer relationship between the calling function and the called function. When you call a function in the calling function, the function name in brackets after the parameter called "actual parameters."

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);
}

Actual parameter reference method is invoked when the contents of the real transmission, the formal parameters for receiving the contents of the parameter arguments.

Value is passed and passed by reference
above mentioned, when we call a reference function when will the actual parameters passed to the formal parameters. However, programming languages, in both cases the transfer of this transfer process, that value is passed and passed by reference. We look at the programming language is how to define and deliver value zone and passed by reference.

Value transfer (pass by value) refers to when calling function copies the actual parameters passed to a function, so if modify parameters in functions will not affect the actual parameters.

Passed by reference (pass by reference) means that when you call the function directly address the actual arguments passed to the function, then to modify the parameters carried out, it will affect the actual parameters in functions.

With the above concepts, then you can write code practice, take a look at Java, in the end is passed by value or passed by reference, so the easiest piece of code out:

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   int i = 10;
   pt.pass(i );
   System.out.println("print in main , i is " + i);
}

public void pass(int j) {
   j = 20;
   System.out.println("print in pass , j is " + j);
}

The above code, we modify the value of the parameter j in the process pass, then the value of the parameter respectively pass printing method and the main method. The output results are as follows

print in pass , j is 20
print in main , i is 10

Visible, internal modifications to pass method name value and the actual value of the parameter i does not change. So, according to the above definition, it was the conclusion: Java way to pass is passed by value.

However, it was soon questioned the (ha ha, so do not jumping to conclusions slightly.). Then they will move out of the following code:

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   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);
}

The same method is a pass, the same is to modify the value of the parameter in the pass method. Output:

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

After a pass execution method, at the arguments now being changed, it passed by reference, as defined above, the actual value of the parameter is changed, it is not passed by reference yet. Thus, according to the above two pieces of code, a new conclusion was obtained: Java method, when an ordinary transfer type is passed by value, when the type of the object is passing reference.

However, this expression is still wrong. I do not believe you can see below this parameter type passed as a parameter object:

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   String name = "Hollis";
   pt.pass(name);
   System.out.println("print in main , name is " + name);
}

public void pass(String name) {
   name = "hollischuang";
   System.out.println("print in pass , name is " + name);
}

The above code output is

print in pass , name is hollischuang
print in main , name is Hollis

This is what explanation do? Also passing an object, but the original value of the parameter has not been modified, do not pass the object and becomes the value passed?

Java in the value of the transfer
above, we cite three examples, the result is not the same performance, which is leading to a lot of beginners, and even many senior programmer for the Java transfer types are confused reason.

In fact, I want to tell you that the above concept is not wrong, just an example of the code in question. Come, I come to you draw the main points of the concept, and then a few real case in point.

Value transfer (pass by value) refers to when calling function copies the actual parameters passed to a function, so if modify parameters in functions will not affect the actual parameters.

Passed by reference (pass by reference) means that when you call the function directly address the actual arguments passed to the function, then to modify the parameters carried out, it will affect the actual parameters in functions.

Well, I'll give you sum up, what value is passed and references focus on difference of transfer yes.

Several examples of the pass we've seen above, only concerned about whether the actual parameter has changed. User object passed as is, we try to change the value of his name attribute, then check whether there is a change. In fact, the experimental methods are wrong, of course, the conclusion will be a problem.

Why experimental method wrong? Here we give an example of image. Come-depth understanding of what value is passed and passed by reference, then you will know why wrong.

Do you have a key, when your friends want to go to your home, if you put your keys directly to him, which is passed by reference. In this case, the key to this if he did anything like he carved his name on a key, then this key back to you, on your own keys will be more out of his engraved name.

Do you have a key, when your friends want to go to your home, you engraved a new key to him, still in his own hands, which is passed by value. In this case, he put what key do this will not affect this key in your hand.

However, regardless of the above cases, you give your friend took his keys, into your home, your home television smashed. Then you say you will not be affected? And when we pass the value of the method, the object is to change the user name attribute, not that in "hit television" it. Not that you change the key, but the key to open the house.

Also take an example to the above example, we really change the parameters, see what happens?

public static void main(String[] args) {
   ParamTest pt = new ParamTest();

   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 = new User();
   user.setName("hollischuang");
   user.setGender("Male");
   System.out.println("print in pass , user is " + user);
}

In the above code, we pass method, the user object has changed, the output results are as follows:

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

Let's draw a picture, look at what is happening throughout the process, then I'll tell you why Java only passed by value.

Explain a little lower this figure, when we create a User object in the main the time, open up a heap memory, which holds data such as name and gender. Hollis then holding the memory address 0x123456 (FIG. 1).

When trying to pass method call, and hollis passed as actual parameters to the formal parameters of the user when the address 0x123456 to the user will, at this time, the user can point to this address (FIG. 2).

When then modified in pass method parameters, namely user = new User () ;, will re-open up a 0X456789 of memory assigned to the user. After the user face any modifications will not change the contents of memory 0X123456 (Figure 3).

This transfer is above what passed? Certainly not passed by reference, if it is passed by reference, then the implementation of user = new User (); when the actual reference parameters should be changed to point to 0X456789, but not actually.

By concept we can know, here is the reference to the address of the actual parameters of a copy, it is passed to the formal parameters. Therefore, the above parameter value is actually transmitted, the address of the object reference as argument values ​​passed to the formal parameters.

Let's review the example of the "TV hit" before, the transfer process to see that example of what happened.

Similarly, during the transmission parameters, the actual parameter 0X1213456 address is copied to the parameter, but, in this method, and no modification parameter itself, but the modified address parameter held in the memory Content.

Therefore, the difference value is passed and not passed by reference deliver content. But in the end there is no argument to be a copy of the formal parameter. In determining the content of the argument have not affected the time to look at what pass is, if you pass addresses, then look at this address change will not be affected, instead of watching the object pointed to changes in address. Like the relationship between keys and house.

Well, in that case, why the above is also a transfer target, deliver the performance results of the String object and the User object is not the same? We use pass method name = "hollischuang"; try to change the value of the name, address accidentally changed the name directly references. Because this code will be a new String, then references to the name, that is equivalent to:

name = new String("hollischuang");

而原来的那个"Hollis"字符串还是由实参持有着的,所以,并没有修改到实际参数的值。

所以说,Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。

总结
无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy)。在求值策略中,还有一种叫做按共享传递(call by sharing)。其实Java中的参数传递严格意义上说应该是按共享传递。

按共享传递,是指在调用函数时,传递给函数的是实参的地址的拷贝(如果实参在栈中,则直接拷贝该值)。在函数内部对参数进行操作时,需要先拷贝的地址寻找到具体的值,再进行操作。如果该值在栈中,那么因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响。如果原来拷贝的是原值在堆中的地址,那么需要先根据该地址找到堆中对应的位置,再进行操作。因为传递的是地址的拷贝所以函数内对值的操作对外部变量是可见的。

简单点说,Java中的传递,是值传递,而这个值,实际上是对象的引用。

而按共享传递其实只是按值传递的一个特例罢了。所以我们可以说Java的传递是按共享传递,或者说Java中的传递是值传递。

-----------------------------------本文转载自公众号 Hollis-----------------------------------------

Guess you like

Origin www.cnblogs.com/jichi/p/12031279.html