This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.

This article reprinted, reprint articles to: www.zhihu.com/question/52…

Issue an overview

Cloneable (Cloneable) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) : Cloneable (clone) Arrays also seem to implement the Cloneable interface. How is this implemented?

Best answer

This is a design flaw of Java. It’s a terrible design.

If Java were redesigned today, it probably wouldn’t look like this. Some of the design requirements/limitations were that Java objects should support Clone functionality.

Clone () is a special polymorphic operation, preferably with direct support from the JVM. Early Java did not support annotations. Support begins with Java 5.

Early Java supported “declare multiple inheritance” in the form of interfaces. Early Java did not support any “implement multiple inheritance” (” multiple inheritance “for short). Starting with Java 8, this can be implemented through the default Method of the interface. Put these together and you get the bad design of the Cloneable interface.

How can I put it? First, we need to be able to mark which classes are clone able. In Java, type-level metadata can be represented in several ways:

  1. The inherited base class
  2. Implemented interface
  3. Modifiers implemented directly in the Class file via Access Flags
  4. Using the annotation,

Obviously, when Java was designed, whether or not a class should support Clone is an important attribute, but not important enough to justify giving it a keyword modifier to modify the class declaration, so (3) should not be used. Java classes, however, are single-inherited, and it would be a bit awkward (but not impossible, come to think of it) to consume the “base class” resource for marking purposes. So (1) is not so good either. So we’re just left with PI (2) and PI (4).

But early Java didn’t support (4), so (2) was all that was left. Second, the semantics of clone() are unique, and it is best to have direct SUPPORT from the JVM. Therefore, if the user code is to customize clone(), it is best to call the base implementation provided by the JVM and then add its own functionality (as is often done simply by calling super.clone() in clone() first). For the JVM to support it directly, you have to find a place in the API to expose this support to Java code calls. The most intuitive way to do this is to put the basic implementation of the Clone () method in a base class that all clone-able classes can access, and let clone-able classes inherit the implementation. But as discussed in the previous point, we don’t want to put the basic implementation of Clone () in a special base class, consuming the unique “base class” slot of a Java class. Where else would you put it? Just put it on java.lang.Object, the common base class for all Java classes.

So what’s the difference between a class that implements the Cloneable interface and a class that doesn’t? From the JVM’s point of view, this is just a tag interface. The cloneable tag is implemented, and the cloneable tag is not implemented. Then, in the basic implementation of Clone (), the JVM checks to see if the class of the object to be cloned is marked with this flag, and throws an exception if it is not. It’s that simple. Array types in Java are implemented directly by the JVM without corresponding Java source files. How the JVM implements it is up to them. Chapter 10. Arrays references the demo code from Chapter 10:

An array thus has the same public fields and methods as the following class:

class A<T> implements Cloneable.java.io.Serializable {
    public final int length = X;
    public T[] clone() {
        try {
            return (T[])super.clone();
        } catch (CloneNotSupportedException e) {
            throw newInternalError(e.getMessage()); }}}Copy the code

Note that the cast to T[] in the code above would generate an unchecked warning (§5.1.9) if arrays were really implemented this way.