Tag Archives: Object.clone()

Access permission problem caused by object. Clone() method

Front end developers must read! Starting from scratch, teach you to build a low code website platform in stages>>>

In the process of learning Java, I saw such a sentence in “Java core technology” (Volume 1), “because the clone () method in the object class is protected, it cannot be called directly in the form of anobject. Clone(). I didn’t understand when I saw it at that time. When I studied before, I had this understanding of protected

The protected modified classes and properties are visible to yourself, this package and its subclasses

Object is the superclass of all classes by default, and the clone () method is the method in object. According to this understanding, the clone () method can be called by any class, but in fact, when we try to run the following code

public class test {
    public static void main(String... args){ test2 a = new test2(); a.clone(); } } class test2 { } 

The editor will prompt you directly

‘clone() has protected access in ‘java.lang.Object’’

In fact, the reason for this situation is that the previous understanding of protected is somewhat one-sided, and the accurate understanding of protected is wrong

For protected members or methods, it is necessary to check whether the molecular class and superclass are in the same package. Subclasses that are not in the same package as the base class can only access the protected members inherited from the base class, but not the protected members of the base class instance itself. Protected and public are the same in the same package

For this example, although test and test2 are subclasses of object, because the clone() method is protected and test and object are not in the same package, the method in test can only access the protected members (that is, clone() method) inherited from the base class (that is, object in this example), You cannot access the protected members of the base class instance itself (that is, you try to call the clone() method in a way like a. clone())

public class test {
    public static void main(String... args){ test a = new test(); a.clone(); } } class test2 { } 

In fact, when we call the clone () method in the above way, note that a is an instance of test instead of test2, and the compiler will prompt you

Unhandled exception:java.lang.CloneNotSupportedException

Although the program still can’t run normally, it’s not the previous permission problem that prevents the program from running. This also shows that test can call its own clone () method inherited from the object. As for the origin of this exception, let’s check the source code of the object. Clone () method and find the following content

/**
     * @return     a clone of this instance.
     * @throws  CloneNotSupportedException  if the object's class does not
     *               support the {@code Cloneable} interface. Subclasses
     *               that override the {@code clone} method can also
     *               throw this exception to indicate that an instance cannot
     *               be cloned.
     * @see java.lang.Cloneable
     */
    @HotSpotIntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException; 

As you can see, the object. Clone () method is a native method. In short, a native method is an interface for Java to call non java code. The speed of the general native method is much faster than the program you write, which is why when we want to clone an object, we recommend using the object. Clone () method instead of using java code to achieve such a function (although it can also achieve the desired results). In addition to the native keyword, let’s look at some of the annotations for this method

@Return: indicates the clone of an instance returned by this method, which is not much different from our expectation

@Throws: in fact, this is the reason why our program just now can’t run normally. The following content of @ throws shows that if a class doesn’t implement the Cloneable interface, or a subclass attempts to override the clone method, will throw an exception named clonenotsupportedexception

In practice, if you want to use the clone() method, you will generally do the following operations:

1. To implement the Cloneable interface, let’s say more. In fact, Cloneable is a tag interface . The so-called tag interface, as the name suggests, is an interface used to tag classes. That is to say, this interface actually has no content. We can check the Cloneable source code and see the relevant explanation

/**
 * A class implements the <code>Cloneable</code> interface to
 * indicate to the {@link java.lang.Object#clone()} method that it
 * is legal for that method to make a
 * field-for-field copy of instances of that class.
 */
public interface Cloneable { } 

2. Rewrite the clone () method to public, which has been explained before. The protected permission can not meet the actual needs
3. Call the clone() method of the parent class, and add another content here. In fact, the object. Clone() method implements shallow cloning, not deep cloning. If you want to realize deep cloning, you need to rewrite the clone method reasonably. Here is a brief explanation of the two clones

All variables of the object copied by shallow clone have the same value as the original object, while all references to other objects still point to the original object. In other words, there are still some associations between the cloned object and the previous object, and the degree of cloning is not high, so it is also called shallow cloning

All the variables copied by deep clone have the same values as the original objects. The variables that refer to other objects will point to the copied new objects instead of the original ones. In other words, deep copy copies all the objects referenced by the object to be copied

Here is also a simple example to realize the above method

public class Player implements Cloneable { private String name; private int age; private Coach coach; public Player(String name, int age, Coach coach) { this.name = name; this.age = age; this.coach = coach; } public String getName() { return name; } public int getAge() { return age; } public Coach getCoach() { return coach; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public Player clone() { Player player = null; try { player = (Player) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return player; } public static void main(String... args) { Coach coach = new Coach("Popvinch"); Player duncan = new Player("Duncan", 42, coach); Player clone = duncan.clone(); clone.getCoach().setName("Kerr"); clone.setName("Curry"); clone.setAge(30); System.out.println("His name is " + duncan.getName() + ",His age is " + duncan.getAge() + ",His coach is " + duncan.getCoach().getName()); System.out.println("His name is " + clone.getName() + ",His age is " + clone.getAge() + ",His coach is " + clone.getCoach().getName()); System.out.println(duncan.getCoach(