Why is Object.clone() protected and why does calling clone() on a class without Cloneable fail?
answer
- clone() = field-by-field shallow copy, no constructor
- protected → opt in & widen to public yourself
- Cloneable is a marker (no methods), just a flag
- No Cloneable → CloneNotSupportedException (checked)
- Prefer copy constructor / copy factory
basics
~20 sclone() is protected so it isn't a public API by default. Object.clone() checks for the Cloneable marker interface; without it, it throws CloneNotSupportedException. Cloneable carries no methods — it just flips clone() from throwing to copying.
solid answer
~40 sObject.clone() is declared protected, so a class can't be cloned from the outside unless it deliberately overrides clone() and widens it to public. Internally, Object.clone() makes a field-by-field shallow copy, but it first checks whether the object's class implements the Cloneable marker interface; if not, it throws CloneNotSupportedException. Cloneable is a marker (no methods) — it doesn't supply clone(); it merely signals to Object.clone() that the author opted in. This is an unusual design: the interface enables a method on a different class (Object) rather than declaring behavior. The default copy is shallow (mutable referenced objects are shared), so deep copies need manual work, clone bypasses constructors, final fields are awkward, and CloneNotSupportedException is checked. Effective Java therefore recommends copy constructors or copy factories over Cloneable/clone in most code.
go deeper
Knows clone() copies an object and that there's a Cloneable interface involved.
Explains protected access, the marker-interface mechanism, CloneNotSupportedException, and shallow-vs-deep copying.
Articulates why Cloneable is a flawed design, the super.clone() and final-field pitfalls, and prefers copy constructors/factories with reasoning.
Sets team conventions (ban clone, standardize on copy factories/records), reasons about immutability removing the need to copy at all, and serialization-based deep copy trade-offs.
## What `clone()` does `Object.clone()` creates a **new object that is a field-by-field copy** of the original — same class, same field values, without running a constructor. By default this copy is **shallow**: primitive fields are copied by value, but reference fields are copied as references, so the original and the clone *share* the same referenced sub-objects. ## Why it's `protected` The method is declared `protected Object clone()`. `protected` means only the class itself and subclasses (and same-package code) can call it — it is **not** part of the public API. Rationale: cloning is a capability a class must *opt into and expose deliberately*. If you want public cloning, you override it and widen the access: ```java public class Point implements Cloneable { int x, y; @Override public Point clone() { // widened to public, covariant return try { return (Point) super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(e); } } } ``` ## Why `Cloneable` is required `Cloneable` is a **marker interface** — it declares **no methods**. Yet `Object.clone()` does this: if `this` is **not** an instance of `Cloneable`, it throws **`CloneNotSupportedException`** (a *checked* exception). So `Cloneable` doesn't provide `clone()`; it acts as a **flag** that changes the behavior of a method defined on a *different* class (`Object`). This is widely considered a design wart — an interface that modifies the behavior of a protected method elsewhere rather than declaring a contract. ```java class NotCloneable { } Object o = new NotCloneable(); // o.clone() would throw CloneNotSupportedException because // NotCloneable does not implement Cloneable ``` ## The pitfalls (why Effective Java discourages it) - **Shallow by default**: shared mutable sub-objects must be deep-copied manually (clone each mutable field, recursively). - **Bypasses constructors**: invariants enforced in a constructor are skipped; the object appears without construction. - **`final` fields**: clone can't reassign `final` reference fields to deep copies, which conflicts with deep cloning. - **Checked exception**: `CloneNotSupportedException` clutters call sites even when you know the class is Cloneable. - **`super.clone()` requirement**: a correct clone must call `super.clone()` (not `new`) so the runtime type is right through the hierarchy. ## The recommended alternative A **copy constructor** (`new Point(existing)`) or **copy factory** (`Point.copyOf(existing)`) is clearer, runs normal construction (preserving invariants), works with `final` fields, doesn't need `Cloneable`, throws no checked exception, and lets you choose shallow vs deep explicitly. Effective Java Item 13: 'Override clone judiciously' — usually prefer copy constructors/factories.
- What's the difference between a shallow and a deep clone?A shallow clone copies field values directly, so reference fields point to the same sub-objects shared with the original. A deep clone recursively copies the referenced mutable objects too, so the copies are fully independent.
- Why does Effective Java recommend copy constructors over clone()?Copy constructors run normal construction (preserving invariants), work with final fields, need no Cloneable marker, throw no checked exception, and let you explicitly choose shallow vs deep — avoiding all of clone's design hazards.
saying these in an interview costs you the question
- Saying Cloneable declares the clone() method
- Assuming clone() does a deep copy by default
- Forgetting clone bypasses constructors and invariants
- Not calling super.clone() and using new instead
- Claiming you can clone any object regardless of Cloneable