🔌 Interfaces & Abstraction · Intermediate

Marker interfaces in Java

Serializable, Cloneable and why annotations often replace them.

🧩 The mysterySerializable contains zero methods. Implementing it costs nothing — yet forgetting it can crash your program. How can an empty interface matter?

A sticker, not a skill

A marker interface has no methods. Implementing it just tags the class, like a "fragile" sticker on a box — it adds nothing inside, it tells others how to treat it. Classics: **Serializable, Cloneable, RandomAccess**.

class Photo implements Serializable { }
// no methods to write — it's a tag

Who reads the sticker?

Other code checks the tag. Object.clone() checks for **Cloneable at runtime and throws CloneNotSupportedException** if it's missing. Since a marker is a real type, instanceof can test for it: "text" instanceof Serializable is true, a plain new Object() is not.

🔮 Predict it

Clone without the sticker

Sheep never implements Cloneable. What happens?

class Sheep {
    Sheep twin() throws Exception {
        return (Sheep) clone();
    }
}
void main() throws Exception {
    new Sheep().twin();
}
  1. Returns a copy quietly
  2. Throws CloneNotSupportedException
  3. Compile error: clone() is protected
Show the answer

It compiles: a class may call its own inherited protected clone(). But at runtime Object.clone() sees no Cloneable tag and refuses.

⚠️ The trap

Cloneable doesn't give you clone()

Implementing Cloneable does not add a public clone() method — the interface is empty. Object.clone() stays protected. To let others copy your objects you must override clone() yourself, usually as public.

🤔 Think first

Interface or annotation?

Annotations can tag classes too. Why might void save(Serializable s) be better than an @Saveable annotation?

Think about it, then reveal the answer

A marker interface is a type, so a parameter can require it and the compiler rejects wrong arguments. An annotation can't be used as a type — but it can carry values and be placed on fields and methods, which is why annotations often replace markers today.

💼 In the real world

Markers at work

RandomAccess quietly speeds up JDK algorithms: Collections.binarySearch checks whether a list is instanceof RandomAccess (like ArrayList) to choose fast index access instead of walking node by node. Serializable still guards session and cache objects.

Key takeaways

  1. Marker = empty interface used as a tag
  2. Classic examples: Serializable, Cloneable, RandomAccess
  3. Object.clone() throws CloneNotSupportedException unless the class is Cloneable
  4. Annotations are the modern alternative; markers give compile-time type checks

💡 A 'fragile' sticker on a box adds no contents — it just tells handlers how to treat it.

🤯 Did you know?

Every Java array is secretly tagged with two markers: new int[0] instanceof Cloneable and instanceof Serializable are both true.

Practice questions

What does this print?

class Sheep {
    Sheep copy() throws CloneNotSupportedException {
        return (Sheep) clone();
    }
}
void main() throws Exception {
    new Sheep().copy();
    System.out.println("cloned");
}
  1. cloned
  2. Throws CloneNotSupportedException
  3. Compile error: clone() is protected
  4. Prints nothing
Check your answer

Throws CloneNotSupportedException. Object.clone() checks for the Cloneable marker at runtime. Sheep doesn't implement it, so clone() throws.

What does this print?

Object a = "text";
Object b = new Object();
System.out.println(a instanceof Serializable);
System.out.println(b instanceof Serializable);
  1. true false
  2. false false
  3. true true
  4. Compile error
Check your answer

true false. String implements Serializable; plain Object doesn't. A marker interface is a type, so instanceof can test for it. (java.io is auto-imported in a compact source file.)

Next: why do pros write List<String> names = new ArrayList<>() instead of ArrayList<String> names?