Java Advanced features: clone () method

Source

public class Objcet{
    protected native Object clone() throws CloneNotSupportedException();
}

From the source.

  • First: clone Objcet class () method is a native method. The efficiency of the method is generally non-native native method (generally not written in java language) Java is much higher than that. This also explains why the use of Object clone () method, rather than a new first class, and then copy the original object to the new object, although this can be achieved clone function. (JNI Java Native Interface is an abbreviation of Starting with Java 1.1, Java Native Interface (JNI) become part of the standard java platform, which allows Java code and code written in other languages ​​to interact .JNI beginning to native compiled language, especially designed for C and C ++, but it does not prevent you from using other languages, as long as the calling convention supported it. use code that interacts with the local java compiled, typically lost platform portability. However, in some cases this is done under acceptable, even necessary, for example, using some of the old library, the hardware, the operating system interacts, or to improve performance .JNI standard procedure at least ensure that native code can work to achieve in any Java virtual machine under.)
  • Second: clone Object class () method is modified protected modifier. (On the protected modifier to see my other article.) This means that the clone () method is only visible to java.util.lang packages, and inherit a subclass of Object visible. Of course, all classes inherit the Object class.
    • Why use protected modified it?
      For safety, security consider two aspects. First we have to clone an Employee object, there should only be able to clone the Employee class Employee object. Use the protected modifier to ensure that other unrelated classes can not be cloned Employee object. Followed by Object ignorant of the object to be copied, it will only be replicated by domain, if all the objects in the data field are numerical or other basic types, copy these fields without any problems. However, if the object contains a reference to the child object, copy the same sub-domain will get another reference object, so that the original object and cloned object will share some information. So the default copy is shallow copy. To use the clone method anywhere, we have to change it to public type, and implement the Cloneable interface. If a start is public, we will tell in the end is a shallow copy or a deep copy. Cloneable to use protected and bound by the class designer to understand their cloning process.

      Cloneable interface is a marker interface, it does not contain any methods needs to be implemented. If a clone object request, but does not implement this interface, receiving a check exception is generated, because there is the clone method implemented using the default interface instanceof determination.
      Here the code is given

//cloneTest.java
package com.testbase.clone;

public class cloneTest {
    public static void main(String[] args){
        // 虽然我们已经实现了Cloneable接口,不会产生异常
        // 但是编译器并不知道,会报错,所以这里要捕获异常
        try
        {
            Employee tobin = new Employee(30000);
            int salary = tobin.getSalary();
            System.out.println(salary);
            Employee shengsheng = tobin.clone();
            int shengSalary = shengsheng.getSalary();
            System.out.println(shengSalary);
        }
        catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
    }
}
//Employee.java
package com.testbase.clone;

public class Employee implements Cloneable
{
    private int salary;
    public Employee()
    {

    }
    public Employee(int asalary)
    {
        salary = asalary;
    }
    @Override
    public Employee clone() throws CloneNotSupportedException
    {
        Employee cloned = (Employee) super.clone();
        return cloned;
    }

    public int getSalary() {
        return salary;
    }
}
  • Third: Object.clone () method returns an Object object. We must be cast to get the type we need. (Cast will succeed it? If you override the clone method with some success. But if not rewrite, can not be converted .clone is the parent class Object, down not modeling, sub-class overrides the clone method is to copy the current class object, to temporarily switch Object, can also cast back)
    gives some error codes. Employee.java copy because the copy is not successful in certain other classes. Because the characteristics of the clone method of the Object protected class. Only inherited its subclasses and java.util.lang package can call the clone () method. Therefore, selection tests in the sub-class Employee.
package com.testbase.clone;

public class Employee implements Cloneable
{
    private int salary;
    public Employee()
    {

    }
    public Employee(int asalary)
    {
        salary = asalary;
    }
//    @Override
//    public Employee clone() throws CloneNotSupportedException
//    {
//        Employee cloned = (Employee) super.clone();
//        return cloned;
//    }

    public int getSalary() {
        return salary;
    }

    public static void main(String[] args){
        try
        {
            Employee tobin = new Employee(30000);
            int salary = tobin.getSalary();
            System.out.println(salary);
            Object shengsheng = tobin.clone(); //这里不能强制类型转换
            int shengSalary = shengsheng.getSalary();//这里报错,因为Object没有getSalary方法
            System.out.println(shengSalary);
        }
        catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
    }
}

Deep and shallow copy copy

Shallow copy: copy references, but does not copy the reference point of the object, a reference to the object to be modified copy, two copies will be modified. If the source and target shallow copy of the shared sub-objects are immutable, then this share is safe. For example, the String class. Or in the lifetime of the object, the child object contains the same has been constant, the method is not changed it will change, there is no method generates a reference to it, this case is also safe.
Deep copy: sub-objects may also change the copy. To make a deep copy, it is necessary to rewrite layers of the clone method.

  • An array is a deep copy. All of array types have a public clone () method, you can use this method to create a new array.
int[] a = {1,2,3,4};
int[] cloned = a.clone();
cloned[0]=11;

Copy object serialization achieved

Common interview questions

1. Why copy

  • Because an object instance we now need to save some of RMS, we hope to generate a same as the original object, modify this object does not change the properties of the original object.

2. deep copy and shallow copy distinction

  • Generate a shallow copy of a new copy of the base data type, a reference type, just copied references, reference points to that memory space is not copied
  • Deep copy of that memory space also references to copy a (new memory). In other words make a deep copy of the object referenced by the copied objects are also copied again.

Particularity 3.String clones out there? StringBuffer and StringBuilder it?

  • Can automatically deep copy of the basic data types. While shallow copy is a reference type. String is a reference type of special case. Because String can not be modified. It is equivalent to a deep copy, it is safe. Since String class is immutable, many modifications operation String class are new objects by copying process. So when we modify the value of the String property inside clone objects before and after, in fact, point to the new memory space. There will be no effect on the source object in front of the clone, similar to a deep copy. Although it is a reference type, but does not affect our deep copy of use.
    For StringBuffer and StringBuilder, you need to take the initiative to clone rewritten. Otherwise, it is shallow copy.

4. common way to achieve the target clone what, specifically how to do?
There are three common ways.

  • By himself wrote a clone method, new one and the same object assignment to realize the depth of cloning, tedious and error-prone.
  • By implementing Cloneable interface and override the clone method of the Object class, it is divided into two shades of ways.
  • The sequence and to deserialize objects by true Serializable interface and deep copy.

Codes, primarily the second and third methods.
By implementing Cloneable interface and override the Object class clone () method to achieve shallow clone approach: Object class default clone method implementation is ultimately a native method (if the clone class does not implement the Cloneable interface and calls the clone method of Object will throw a CloneNotSupportedException out, because there is the clone method implemented using the default interface determination instanceof), relatively higher efficiency, a default implementation is to open up the same space and the original object in memory, and then copying the contents as the original object, is the value of the basic data types replication, while non-base types hold only references to the object, it will result in the types of variables and non-essential clone original object corresponding variable pointing to the same object.
Shallow copy.

class Employee implements Clonealbe{
    public Employee clone() throws CloneNotSupportedException
    {
        return (Employee) super.clone();
    }        
}

Deep copy

class Employee implements Clonealbe{
    public Employee clone() throws CloneNotSupportedException
    {
        Employee cloned = (Employee) super.clone();
        cloned.hireDay = (Date) hireDay.clone();
        return cloned();
    }        
}

The sequence and to deserialize objects by true Serializable interface and deep copy. (Not yet learned)

class CloneUtil {  
   public static <T extends Serializable> T clone(T obj) {  
       T cloneObj = null;
       try {
           ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
           ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
           objOut.writeObject(obj);  
           objOut.close();  
           ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); 
           ObjectInputStream objIn = new ObjectInputStream(byteIn);  
           cloneObj = (T) objIn.readObject();  
           objIn.close();
       } catch (IOException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       }  
       return cloneObj;  
   }
}
 
 
class InfoBean implements Serializable {  
   public String name;
   public int age;
}
 
 
class PeopleBean implements Serializable {  
   public String vipId;
   public InfoBean infoBean;
 
   public Object clone() {
       return CloneUtil.clone(this);
   }  
}

Reference article:
https://www.cnblogs.com/gw811/archive/2012/10/07/2712252.html
https://blog.csdn.net/qq_26857649/article/details/84316081

Guess you like

Origin www.cnblogs.com/zuotongbin/p/11723346.html