How should the return type and access modifier of an overridden clone() be declared, and why?
answer
- Base: protected Object clone() throws CNSE
- Widen protected → public
- Covariant return: return own type, not Object
- Cast inside (super.clone()→Object), no cast for callers
- Swallow the impossible CloneNotSupportedException
basics
~20 sObject.clone() is protected and returns Object. When you override it, make it public so callers can use it, and use a covariant return type (return your own class) so callers don't have to cast the result.
solid answer
~40 sOn Object, clone() is declared protected with return type Object and throws CloneNotSupportedException. When a class overrides clone() to support copying it should: (1) widen access from protected to public, otherwise external code still cannot call it; and (2) use a covariant return type — return the class's own type instead of Object. Java has allowed covariant return types since Java 5, so an override may return a subtype of the overridden method's return type. This lets callers write Foo copy = foo.clone() without a cast, which is both cleaner and type-safe. Conventionally the override also drops the throws clause (or catches the exception internally) since a Cloneable class can never actually throw CloneNotSupportedException. Together these make clone() pleasant to call despite Object's awkward base signature.
go deeper
Knows clone() should be made public and that returning your own type avoids a cast.
Writes the canonical override: public, covariant return, internal cast of super.clone(), catch-and-rethrow of the impossible exception.
Explains the access-widening rule, covariant returns since Java 5, and why the checked exception can be swallowed for a Cloneable class.
Sees these as polish on an inherently flawed API and would still steer teams to copy constructors; cites covariant returns as a general override capability beyond clone.
## The base signature you are overriding On `java.lang.Object`: ```java protected Object clone() throws CloneNotSupportedException ``` Three friction points for callers: it is **protected** (not callable from outside the class/package/subclass), it returns **Object** (forces a cast), and it declares a **checked exception** (forces a try/catch even when impossible). ## Fix 1 — widen access to public Access modifiers in an override may only stay the same or **widen** (you can go protected→public, never public→protected). To let arbitrary callers clone your object you must override and declare it `public`: ```java @Override public Item clone() { ... } ``` If you leave it protected, `someItem.clone()` still won't compile from unrelated code. ## Fix 2 — covariant return type Since **Java 5**, an overriding method may declare a return type that is a **subtype** of the overridden method's return type — a **covariant return type**. Because every class is a subtype of `Object`, you can return your own class: ```java @Override public Item clone() { try { return (Item) super.clone(); } // cast needed INSIDE (super.clone() returns Object) catch (CloneNotSupportedException e) { throw new AssertionError(e); } } ``` The cast is needed *inside* the method (because `super.clone()` is typed as `Object`), but **callers** get `Item` directly: ```java Item copy = item.clone(); // no cast at the call site ``` Without covariance, every caller would write `(Item) item.clone()`. Covariant returns push that one cast into the single override and out of every call site. ## Fix 3 — drop the checked exception A class that implements `Cloneable` can never actually have `super.clone()` throw `CloneNotSupportedException`, so idiomatic overrides catch it internally and rethrow an `AssertionError`, removing the `throws` clause from the public signature. Callers then need no try/catch. ## Putting it together The conventional, caller-friendly clone override is: ```java public class Item implements Cloneable { @Override public Item clone() { // public + covariant return try { return (Item) super.clone(); } catch (CloneNotSupportedException e) { // impossible here throw new AssertionError(e); } } } ``` This trio — widen to public, covariant return, swallow the impossible exception — is what makes an inherited-from-`Object` `clone()` usable. (None of it fixes clone's deeper design problems; it just makes the *call site* clean.) ## Term definitions - **Covariant return type:** an override returning a subtype of the parent method's declared return type — permitted since Java 5. - **Widening access:** an override may make a member *more* accessible (protected→public) but never *less*; narrowing is a compile error.
- Since which Java version are covariant return types allowed?Java 5 (J2SE 5.0). Before that, an override had to declare exactly the same return type as the method it overrode, so clone() overrides returned Object and callers always cast.
- Can an override make clone() less accessible than Object's protected version?No. Overrides may only keep or widen access. protected can become public, but you cannot narrow it to private/package-private — that is a compile error.
saying these in an interview costs you the question
- Leaving clone() protected and wondering why callers can't use it
- Returning Object and forcing every caller to cast
- Thinking you can narrow access (public→protected) in an override
- Believing covariant return types require a special annotation