28

Many articles I've read on the Net about Singleton design pattern mention that the class should override 'clone()' method and in it, throw 'CloneNotSupported' exception. Is this really necessary?

The clone() method by default is protected, so no class (except those in the same package) would be able to call it on that Singleton instance. Plus, if this Singleton does not implement Cloneable, then even if this method is called, it will give a runtime exception. Plus, the constructor being private, we won't be able to subclass it and thus allow for its cloning. So should I still implement this advice for my Singleton classes?

EDIT: Just to clarify: I'm not looking for the best possible way to implement Singleton. I'm just asking about the validity of the advice mentioned above, w.r.t the 'normal' Singleton pattern (and not Enum based Singleton).

shrini1000
  • 7,038
  • 12
  • 59
  • 99
  • 2
    You're asking "If I'm creating singletons the wrong way, which I shouldn't be doing, should I be worried about X". The answer is do it the correct way which makes your question moot. No, you don't have to worry about this. – Brian Roach Feb 16 '12 at 14:47

10 Answers10

26

If you're really going to implement a singleton, use a one-element enum and stop thinking about it.


EDIT: Just to clarify: I'm not looking for the best possible way to implement Singleton. I'm just asking about the validity of the advice mentioned above, w.r.t the 'normal' Singleton pattern (and not Enum based Singleton).

Since you have Effective Java, then you should already be aware of the pitfalls and problems with Cloneable. That said, if you're going to implement a singleton one of the "wrong" ways, no, there's absolutely no reason whatsoever to implement Cloneable and override Object#clone() just to throw CloneNotSupportedException. Object#clone() already does this when the Cloneable interface is absent.

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    +1 - And buy Josh Bloch's excellent [Effective Java](http://java.sun.com/docs/books/effective/) which covers that and more. – Brian Roach Feb 16 '12 at 14:35
  • Yes, I know about it and have the book. But my question is about the cloning advice given in such articles. Are there any cases where this advice makes sense? – shrini1000 Feb 16 '12 at 14:36
  • Since you can't clone an `enum`, no. – Brian Roach Feb 16 '12 at 14:38
  • @shrini1000 why would you heed advice about an irrelevant implementation? – Matt Ball Feb 16 '12 at 14:38
  • 2
    @MДΓΓ БДLL I'm just trying to figure out the thought process behind giving such advice, and if there are any cases where this advice would make sense. – shrini1000 Feb 16 '12 at 14:40
9

@shrini1000, You have a valid question but the suggetsion about clone is very specific to following condition

public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException(); 
}

The above is only necessary if a superclass of a singleton class implements a public clone() method.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
GKP
  • 1,057
  • 1
  • 11
  • 24
  • 1
    Thx Gourabp; but I've seen many examples where the Singleton was not a sub class and yet it was explicitly preventing cloning, hence my question. – shrini1000 Aug 07 '13 at 17:00
3

The below code is for preventing the singleton class to be cloned.Override the clone method and throw new CloneNotSupportedException()

public final class SingeltonCloneTest implements Cloneable {

    /**
     * @param args
     * @return
     */
    private static SingeltonCloneTest instance = null;

    private SingeltonCloneTest() {
     System.out.println("Rahul Tripathi");
    }

    public static SingeltonCloneTest getInstance() {

        if (instance == null) {
            instance = new SingeltonCloneTest();
            return instance;
        }
        return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {

        // TODO Auto-generated method stub
        /*
         * Here forcibly throws the exception for preventing to be cloned
         */
        throw new CloneNotSupportedException();
        // return super.clone();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SingeltonCloneTest test1 = SingeltonCloneTest.getInstance();

        try {
            SingeltonCloneTest test2 = (SingeltonCloneTest) test1.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
Rahul Tripathi
  • 545
  • 2
  • 7
  • 17
  • 2
    By default, the clone() method is marked as protected, but if your SingletonObject extends another class that does support cloning, it is possible to violate the design principles of the singleton. So, to be absolutely positively 100% certain that a singleton really is a singleton, we must add a clone() method of our own, and throw a CloneNotSupportedException if anyone dares try! – abhishek ringsia May 13 '16 at 08:27
2

It is necessary if your Singleton class extends a class that has a visible clone() method defined in its hierarchy.

2

You can avoid cloning by giving already created object by clone method.

public Object clone() {

return singletoneObject;

}
Baby Groot
  • 4,637
  • 39
  • 52
  • 71
2

See https://stackoverflow.com/a/71399/385478 for the safest way to enforce the Singleton pattern. Essentially, make your Singleton an enum rather than a class, with a single INSTANCE value.

Community
  • 1
  • 1
Graham Borland
  • 60,055
  • 21
  • 138
  • 179
2

When writing a class using the Singleton pattern, only one instance of that class can exist at a time. As a result, the class must not be allowed to make a clone.

The singleton pattern says that only one instance of the class exist inside the program, so it is right to raise CloneNotSupportedException in the Clone() method.

aleroot
  • 71,077
  • 30
  • 176
  • 213
1

The best example i found is this:

class SingletonSuper implements Cloneable {
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
   }
}

class Singleton2 extends SingletonSuper {
    // 1. Make all constructors private
    private Singleton2() {
     }

// 2. Declare a private static variable to hold single instance of class
    private static Singleton2 INSTANCE = new Singleton2();

    public static Singleton2 getInstance() {
        return INSTANCE;
   }
  }

 public class SingletonCloningTest {
    public static void main(String[] args) throws Exception {
        System.out.println("Singleton Test!");
         System.out.println("Singleton Instance:" +                         +  Singleton2.getInstance());
        System.out.println("Singleton clone:"
            + Singleton2.getInstance().clone());
    }
}



 The result will:

 Singleton Test!
 Singleton Instance:com.sample.test.Singleton2@50d89c
 Singleton clone:com.sample.test.Singleton2@1bd0dd4
hitesh141
  • 963
  • 12
  • 25
0

You need to override the clone() method only if your singleton class implements Cloneable interface or a class which implements Cloneable interface.

prageeth
  • 7,159
  • 7
  • 44
  • 72
0

As per my understanding you do not need to implement clone() method. Reason: 1. If you don't implement clone method and Cloneable interface it will throw CloneNotSupportedException. 2. clone method is protected and you cannot subclass a singleton class.

Anirban B
  • 507
  • 8
  • 27