How to make default `clone()` in an interface?

149 Views Asked by At

The following code compiles w/o errors:

public interface ICloneable {

    default ICloneable clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    public static void main(String[] args) {

        var object = new ICloneable() {

        };


        System.out.println("ok");
    }
}

But at runtime it says:

ICloneable.java:9: error: clone() in Object cannot implement clone() in ICloneable
        var object = new ICloneable() {
                                      ^
  attempting to assign weaker access privileges; was public

Is it possible to overcome?

1

There are 1 best solutions below

4
On

The following code compiles w/o errors

No it doesn't.

That error you see is in fact a compile error.

Why you get that error

I'm not sure if you understand that clone() is, itself, a method that java.lang.Object already has: javadoc of Object.clone().

A default implementation in an interface never overrides any implementation found anywhere in a class's actual class hierarchy. Meaning, your clone() default impl in your IClonable interface is never used - as all classes have Object in their hierarchy and its clone() takes precedence.

However, IClonable must have a public clone() method - but the clone() you get 'for free' from j.l.Object is protected, hence your code does not compile here.

Is it possible to overcome?

Sure. Various options exist.

The best: Don't call it clone()

Given that clone() is already taken by j.l.Object, find another word. Unless, of course, your intent was to use an interface to force both a default impl and force it public, in which case...

Use abstract classes instead

If ICloneable was an abstract class, you wouldn't get this error.

... otherwise

No, this cannot be fixed. There is no way to tell javac to take the default impl of an interface even though an impl exists in the class hierarchy.

NB: Using IClonable style naming is discouraged. Using the clone() functionality sort of half baked into java (and Object's own clone() is part of this functionality) is strongly discouraged. Make immutable types where possible. If not possible, think through what cloning might mean and just make a method for it. The general principle of 'you can clone me' is broken as a concept. For example, cloning an immutable is pointless, yet, having the clone() method of an immutable type be written as public Object clone() { return this; } is misleading. As a concept, it's not salvagable. There's a reason e.g. arraylist has new ArrayList<T>(otherArraylist) as suggested way to clone one, not List<T> clone = otherArrayList.clone();.