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?
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 thatjava.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, yourclone()
default impl in yourIClonable
interface is never used - as all classes haveObject
in their hierarchy and itsclone()
takes precedence.However,
IClonable
must have apublic
clone()
method - but theclone()
you get 'for free' fromj.l.Object
isprotected
, hence your code does not compile here.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 theclone()
functionality sort of half baked into java (and Object's ownclone()
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 theclone()
method of an immutable type be written aspublic Object clone() { return this; }
is misleading. As a concept, it's not salvagable. There's a reason e.g. arraylist hasnew ArrayList<T>(otherArraylist)
as suggested way to clone one, notList<T> clone = otherArrayList.clone();
.