Value passing and reference passing

When a parameter function is called, the actual argument is passed to the formal argument. However, in a programming language, there are two cases of passing in this process, value passing and reference passing

The difference between

  1. Pass by value means that a copy of the actual parameter is passed to the function when the function is called, so that the actual parameter is not affected if the parameter is changed
  2. Pass by reference refers to that the address of the actual parameter is directly passed to the function when the function is called. Then the modification of the parameter in the function will affect the actual parameter

Value passing in Java

  1. Java only has value passing, not reference passing

  2. For basic data types

    public class ParamTest
    {
    	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); }}Print in pass, j is 20 print in main, I is 10 */
    Copy the code

    Thus, for primitive data types, a reference j is recreated on the stack so that its value is equal to the passed parameter value I, and changing j does not affect I

  3. For reference data types

    • The sample a

      public static void main(String[] args) 
      {
      ParamTest pt = new ParamTest();
         User hello = new User();
      hello.setName("Hello");
         hello.setGender("Male");
      pt.pass(hello);
         System.out.println("print in main , user is " + hello);
      }
      public void pass(User user) 
      {
         user.setName("HelloChange");
         System.out.println("print in pass , user is " + user);
      }
      Print in pass, user is user {name='HelloChange', gender='Male'} print in main, user is user {name='HelloChange', gender='Male'} */
      Copy the code
    • Example 2

      public static void main(String[] args) 
      {
         ParamTest pt = new ParamTest();
         User hello = new User();
         hello.setName("Hello");
         hello.setGender("Male");
         pt.pass(hello);
         System.out.println("print in main , user is " + hello);
      }
      public void pass(User user) 
      {
         user = new User();
         user.setName("HelloChange");
         user.setGender("Male");
         System.out.println("print in pass , user is " + user);
      }
      Print in pass, user is user {name='HelloChange', gender='Male'} print in main, user is user {name='Hello', gender='Male'} */
      Copy the code

      In example 1, calling the User class method changes the attributes of the object at the memory address, but this is not a change to the passed parameter itself. In fact, after hello is passed, a reference to User is created on the stack, pointing to the same address as Hello, that is, to the same object. The change to the object is not a change to the reference hello, which is always on the stack pointing to the object space address

      In example 2, after hello is passed, a user reference is set up on the stack and is equivalent to Hello, but with a new object, the user reference points to a new object, meaning that the value of user in the stack changes, while The value of Hello points to the original object

Copy the object

meaning

Sometimes we need to get a new object, and the existing object are exactly the same, but must be independent, if you use a simple way of assignment, actually refers to the object or the same memory address, a reference may affect another operation, to obtain a copy of this object will need to complete the same new objects

5 kinds of way

  1. setter/getter

    New Sets the properties of the new object using the set/get method

  2. Shallow clone

    • Be reproduced class needs to implement Clonenable interface (not implemented in call clone method will throw CloneNotSupportedException exception), the interface for marker interface (excluding any method)
    • Override the clone() method with the access modifier set to public. The super.clone() method is called to get the desired copy object
    class Address
    {
        private String address;
    
        public String getAddress(a)
        {
            return address;
        }
        public void setAddress(String address)
        {
            this.address = address; }}class Student implements Cloneable
    {
        private int number;
    
        private Address addr;
    
        public Address getAddr(a)
        {
            return addr;
        }
    
        public void setAddr(Address addr)
        {
            this.addr = addr;
        }
    
        public int getNumber(a)
        {
            return number;
        }
    
        public void setNumber(int number)
        {
            this.number = number;
        }
    
        @Override
        public Object clone(a)
        {
            Student stu = null;
            try
            {
                stu = (Student) super.clone();   / / shallow copy
            }
            catch (CloneNotSupportedException e)
            {
                e.printStackTrace();
            }
            returnstu; }}public class Test
    {
    
        public static void main(String args[])
        {
    
            Address addr = new Address();
            addr.setAddress("Hangzhou");
            Student stu1 = new Student();
            stu1.setNumber(123);
            stu1.setAddr(addr);
    
            Student stu2 = (Student) stu1.clone();
    
            System.out.println(Student 1: "" + stu1.getNumber() + "Address:" + stu1.getAddr().getAddress());
            System.out.println(Student 2: "" + stu2.getNumber() + "Address:" + stu2.getAddr().getAddress());
    
            stu2.setNumber(124);
            addr.setAddress("West Lake District");
    
            System.out.println(Student 1: "" + stu1.getNumber() + "Address:" + stu1.getAddr().getAddress());
            System.out.println(Student 2: "" + stu2.getNumber() + "Address:"+ stu2.getAddr().getAddress()); }}/* Output student 1:123, address: Hangzhou student 2:123, address: Xihu Student 2:124, address: Xihu */
    Copy the code

    The new object is obtained by shallow cloning, and its basic datatype member variables are copied without affecting the original object

    If the variable is a reference data type, only the address reference is copied, and whether the variable points to the same address affects each other

    If the variable is String, the address reference is copied. But when modified, it regenerates a new string from the string pool, leaving the original string object unchanged

  3. A deep clone

    • Shallow copy just copies the reference to the ADDR variable, without really opening up another space, copying the value and then returning the reference to the new object
    • In order to achieve true copy objects, rather than pure reference copy. We need to make the Address class copiable and modify the clone method as follows:
    class Address implements Cloneable
    {
        private String address;
    
        public String getAddress(a)
        {
            return address;
        }
    
        public void setAddress(String address)
        {
            this.address = address;
        }
    
        @Override
        public Object clone(a)The Address class is replicable
        {
            Address addr = null;
            try
            {
                addr = (Address) super.clone();
            }
            catch (CloneNotSupportedException e)
            {
                e.printStackTrace();
            }
            returnaddr; }}class Student implements Cloneable
    {
        private int number;
    
        private Address addr;
    
        public Address getAddr(a)
        {
            return addr;
        }
        public void setAddr(Address addr)
        {
            this.addr = addr;
        }
        public int getNumber(a)
        {
            return number;
        }
        public void setNumber(int number)
        {
            this.number = number;
        }
        @Override
        public Object clone(a)
        {
            Student stu = null;
            try
            {
                stu = (Student) super.clone();   / / shallow copy
            }
            catch (CloneNotSupportedException e)
            {
                e.printStackTrace();
            }
            stu.addr = (Address) addr.clone();   // Reference data type variable deep copy
            returnstu; }}public class Test
    {
    
        public static void main(String args[])
        {
    
            Address addr = new Address();
            addr.setAddress("Hangzhou");
            Student stu1 = new Student();
            stu1.setNumber(123);
            stu1.setAddr(addr);
    
            Student stu2 = (Student) stu1.clone();
    
            System.out.println(Student 1: "" + stu1.getNumber() + "Address:" + stu1.getAddr().getAddress());
            System.out.println(Student 2: "" + stu2.getNumber() + "Address:" + stu2.getAddr().getAddress());
    
            stu2.setNumber(124);
            addr.setAddress("West Lake District");
    
            System.out.println(Student 1: "" + stu1.getNumber() + "Address:" + stu1.getAddr().getAddress());
            System.out.println(Student 2: "" + stu2.getNumber() + "Address:"+ stu2.getAddr().getAddress()); }}/* Output student 1:123, address: Hangzhou student 2:123, address: Hangzhou student 1:123, address: Xihu Student 2:124, address: Hangzhou */
    Copy the code
  4. Utility class

    Org.apache.com mons components BeanUtils and PropertyUtils, static method copyProperties(Object O1,Object O2)

  5. serialization

    Serialization is the process of writing an object to a stream, which is a copy of the original object that still exists in memory. Serialization copies not only the object itself, but also the member objects referenced by it, so serialization writes the object to a stream and reads it out of the stream to achieve deep cloning. It is important to note that objects that can be serialized must have classes that implement the Serializable interface, otherwise they cannot be serialized

    class Professor implements Serializable
    {
        String name;
        int age;
        Professor(String name, int age)
        {
            this.name = name;
            this.age = age; }}class Student implements Serializable
    {
        String name;// Constant object
        int age;
        Professor p;// Reference the data type
        Student(String name, int age, Professor p)
        {
            this.name = name;
            this.age = age;
            this.p = p;
        }
        / / deep cloning
        public Object deepClone(a) throws IOException, ClassNotFoundException
        {
            // Write the object to the stream
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            ObjectOutputStream oo = new ObjectOutputStream(bo);
            oo.writeObject(this);
            // Read from the stream
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
            ObjectInputStream oi = new ObjectInputStream(bi);
            return(oi.readObject()); }}public class Test
    {
        public static void main(String[] args) throws IOException, ClassNotFoundException
        {
            Professor p = new Professor("wangwu".50);
            Student s1 = new Student("zhangsan".18, p);
            Student s2 = (Student) s1.deepClone();
            s2.p.name = "lisi";
            s2.p.age = 30;
            System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); 
            // The professor of student 1 does not change}}Copy the code