Pass-by-reference and pass-by-value in Java

  1. Storage of primitive types and reference types in memory
  Data types in Java are divided into two categories, primitive types and object types. Correspondingly, variables also have two types: primitive types and reference types.
  The variable of the basic type saves the original value, that is, the value it represents is the value itself; while the variable of the reference type saves the reference value, and the "reference value" points to the address of the memory space, which represents a reference to an object, not the object itself, the object itself is stored in the space of the address represented by this reference value.
  Java's memory space mainly includes 5 parts: stack area, heap area, static variable or constant storage area, method area, and native method stack. Taking a reference type variable as an example, the "reference value" is an address in the heap area, and the "reference value" is stored in the stack area; the address space pointed to by the "reference value" in the heap area stores the attributes of the object. The stack area follows the declaration cycle of the thread that calls it. When the "reference value" of the heap area is no longer pointed to by the stack area, it will be reclaimed by the GC.    
  Basic types include 8: byte, short, int, long, char, float, double, boolean.
  Reference types include: class types, interface types and arrays.
  Correspondingly, variables also have two types: primitive types and reference types.

  2. The difference between the basic type of the variable and the reference type The
  system allocates space for the basic data type when it is declared:

int a;
a=10;//Correct, because space is allocated when a is declared

   Reference is different, it only allocates reference space to the variable when it is declared, and does not allocate data space: 

Date date;//Open up reference space in stack memory
date=new Date();//Execute instantiation, open up data space to store Date objects, and then pass the first address of the space to the date variable

   Note: "reference" also takes up space. The reference size of an empty Object object is about 4 bytes:

Date a,b; //Open up two reference spaces in stack memory
a = new Date();//Open up a data space for storing Date objects in the heap memory, and assign the first address of the space to a
b = a; //Make b point to the address in the a storage space, which is equivalent to B and a jointly pointing to a storage space in the heap memory

   3. Pass-by-value and pass-by-reference
  The concepts of actual parameters and formal parameters are used here to help understand,
  (1) Pass-by-value:
  When a method is called, the actual parameter passes its value to the corresponding formal parameter, and the function receives the original value At this time, there are two equal basic types in the memory, that is, the actual parameter and the formal parameter. The operations in the following methods are all modifications to the value of the formal parameter, without affecting the value of the actual parameter.
  (2) Pass-by-reference:
  also known as pass-by-address. When the method is called, the reference (address, not the value of the parameter) of the actual parameter is passed to the corresponding formal parameter in the method, and the function receives the memory address of the original value; in the method execution, the content of the formal parameter and the actual parameter are the same , pointing to the same memory address, the operation of the reference in the method execution will affect the actual object.  

package com.itszt.test4;
/**
 * Pass by value and pass by reference
 * Object clone
 */
public class ReferencePKValueTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        ReferencePKValueTest test = new ReferencePKValueTest();
        MyObj obj=new MyObj();
        int a=99;
        test.test1(a);
        System.out.println("The clone method is not taken - before test2() is executed, the attribute value in the object a_ref = " + obj.getA());
        test.test2 (obj);
        System.out.println("The clone method is not taken - after the execution of test2(), the attribute value in the object a_ref = " + obj.getA());
        System.out.println("-----------------------");
        int a_ref1 = obj.getA ();
        System.out.println("Clone method - before cloning, the attribute value in the object a_ref1 = " + a_ref1);
        Object objClone = obj.clone();
        if(objClone==null){
            return;
        }
        test.test2((MyObj)objClone);
        System.out.println("Clone method - after cloning, the attribute value in the object a_ref1 = " + a_ref1);
    }
    private void test1(int a){
        a+=1;
        System.out.println("a_val = " + a);
    }
    private void test2(MyObj obj){
        int a = obj.getA ();
        obj.setA (a+1);
        System.out.println("a_ref = " + a);
    }
}
class MyObj implements Cloneable{
    private int a=99;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

  After the code is executed, the console prints the following:

a_val = 100
The clone method is not taken - before the test2() is executed, the attribute value in the object a_ref = 99
a_ref = 99
The clone method is not taken - after the execution of test2(), the attribute value in the object a_ref = 100
-----------------------
Take the clone method - property value a_ref1 = 100 in the object before cloning
a_ref = 100
Take the clone method - after cloning, the property value a_ref1 = 100 in the object

   In addition, we also need to specially consider String, as well as several basic type wrapper classes such as Integer and Double. They are all immutable (immutable) types. Since they do not provide functions for their own modification, each operation is a new generation. Object, so it needs special treatment, which can be considered as a pass-by-value operation similar to basic data types.

package com.itszt.test4;
/**
 * A wrapper class for basic types, and the String class is similar to passing by value when passing parameters
 */
public class ReferencePKValueTest2 {
    public static void main(String[] args) {
        ReferencePKValueTest2 test2 = new ReferencePKValueTest2();
        //String is similar to the value transfer of basic types, and does not change the value of the actual parameter
        String string="Hello";
        test2.change(string);
        System.out.println(string);

        //StringBuffer and StringBuilder are passed by reference
        StringBuffer stringBuffer=new StringBuffer("Hello");
        test2.change(stringBuffer);
        System.out.println(stringBuffer.toString());
    }

    public void change(String str){
        str=str+"world";
    }
    public void change(StringBuffer str){
        str.append("world");
    }
}

   The console prints as follows:

Hello
Helloworld

   In general, regarding pass-by-value and pass-by-reference, the following conclusions can be drawn:
  (1) Basic data types are passed by value, and modifications to formal parameters will not affect actual parameters;
  (2) Reference types are passed by reference, formal parameters and The actual parameter points to the same memory address (the same object), so the modification of the parameter will affect the actual object; if you want to avoid passing by reference, you can use the clone method;
  (3) String, Integer, Double and other immutable types are special Processing can be understood as passing by value, and the final operation will not modify the actual parameter object.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324732866&siteId=291194637