views:

292

answers:

5

Hi We can restrict the creation of object of a class by making its constructor private. But this constructor could still be called from within the class. Is there any way to prevent this in Java?

Thanks.

+2  A: 

No, there is no way to enforce a single instance of a particular type. The closest you can come is, as you describe, making the constructor private so that only functions within that class can call it. You could do something at runtime (such as throwing an exception if your static instance already exists), but that wouldn't get you anything at compile time.

Adam Robinson
+12  A: 

No, there is no clean way to do this. And really I cannot see a reason to do so. Because if the constructor is private, this means that he can only be called from code within this exact class (no subclasses, or other classes in the package), so if you do not want the constructor to be called, put a comment on it which says so.

Since everyone who is able to use the constructor would be able to remove any measures you put there to prevent the calling of the constructor, it would have no real effect.

Besides, if you need a singleton, then you may want the constructor to be run at least once (except if your idea of a singleton is a purely static class).

frenetisch applaudierend
+3  A: 

The official answer is no. If anybody can get private access to your class he can instantiate it.

However you can do this:

private static int count = 0;

private MyClass(){
    if(++count>1)throw new IllegalStateException(); //allow exactly one instantiation
}
seanizer
Right idea, but this needs synchronization to be bullet-proof. You probably want to use a CountDownLatch for this if going this way.
Sean Owen
Wrong again.....
duffymo
Not sure what to say duffymo, after re-reading the OP, this is the rightest answer here (really, to match the OP's request, it should just always throw an exception, but this is showing how you could still enforce this condition while allowing for one singleton instance, which is a more realistic scenario.) If you believe the question is nonsense, that's a comment on the question, not an answer. But the question does have an answer.
Sean Owen
duffymo: while your answer makes more sense in terms of questioning the question, mine makes more sense in answering it. please explain what's wrong and why again.
seanizer
+8  A: 

If it's private, and you don't want it called within its own class, there's an easy way to prevent such a thing: Don't write the code that calls it more than once. You're the author of the class. Why would you write code to prevent you yourself from doing something that is within your control?

It can't be called outside the class without resorting to reflection. If you don't want it called more than once within the class, then just don't do it. Why write code to prevent an action that you can choose not to do?

Let's review:

We can resrict the creation of object of a class by making its constructor private.

Constructor is private, so it can't be called outside the class unless a client uses the reflection API to undermine access restrictions.

But this constructor could still be called from within the class. Is there anyway to prevent this in Java?

The OP is asking to prevent calling the restricted constructor inside the class.

If these two statements are correct, please explain why there needs to be logic preventing calls to the constructor.

Here's a typical use of a private constructor:

public class Singleton
{
    private static final Singleton instance = new Singleton();

    public static void main(String[] args)
    {
        Singleton singleton = Singleton.getInstance();

        System.out.println(singleton);
    }

    private Singleton() {};

    public static Singleton getInstance() { return Singleton.instance; }

    public String toString() { return Singleton.class.getName(); }
}

I can't see the point of disallowing the call to the private constructor.

duffymo
But every class will have at least one constructor, and it seems the question is restricting calls to it inside the class.
Sean Owen
Yes, but if you read my answer you'll realize how ridiculous the question is. Your down vote is not warranted.
duffymo
The constructor needs still to be written, because if there is no constructor, the compiler will add a public one, which is even worse.
frenetisch applaudierend
No it won't, not if the private constructor is the default. Try it and see.
duffymo
Please explain what you mean by private default constructor. If I create an new Java class without any constructors I can instantiate this class from where ever I want to. To prevent this you need to create a constructor in your class manually.
frenetisch applaudierend
See the example I just posted. That's what I mean. You can't call any constructor on Singleton. Try it and see. The only way you can get a reference to one is by calling the getInstance() method.
duffymo
See what I did? I do have a default constructor, so the compiler won't provide one. I didn't supply any other constructor except that private one, so you can't instantiate this class from wherever you want to. That's the whole point of writing a Singleton this way: to control instantiation.
duffymo
Well that is true, but it does not prevent anyone from adding a method to your class which creates a new instance or changes get instance to call the constructor (which is what I suppose the OP was afraid of). I agree with you, that it makes no point trying to prevent anyone from the inside to call the constructor. But your example contradicts what you said at the beginning of your post: That you do not need to write a private constructor.
frenetisch applaudierend
Yeah but duffymo, your answer says "don't write a constructor". In your example you write a constructor. So ... ? The OP is not wanting to restrict one particular constructor, but *any* constructor call. And while I agree this is not really a vital question, he was specifically asking how to prevent a private constructor from being called more than once. There are ways to do it (below) and your answer didn't address this.
Sean Owen
@all: You are arguing semantics. You all agree, you are just using different ways of describing the same thing. I think duffymo meant: you don't need to put anything in the private constructor, you can leave it empty. This he is incorrectly describing as a 'default constructor', while to everyone else 'default constructor' means 'the public no-arg constructor automatically provided if you don't include any other constructor'.
Skip Head
@Sean Owen - keep up, please. "don't write a constructor" was pointing out that the requirements aren't consistent or logical. Why would you design a class to prevent yourself from calling it more than once? You're the only one calling it if it's private. Why write code to prevent something that you yourself can choose to not do? This discussion is only more ridiculous the longer it goes on.
duffymo
@frenetisch - my real point is that the requirement is self-contradictory and ridiculous.
duffymo
@duffymo +1 I agree with you in this matter, and with your last edit no contradictions anymore :-)
frenetisch applaudierend
@duffymo sorry I touched a nerve but I'm surprised at your tone as well. I will take off the -1 if that helps. I agree your last post clarifies that you aren't answering the question, but rather think it's not a useful one, and I tend to agree. I assume the idea is, well, if some other dev comes in and mucks around with this, and starts writing code that instantiates the object, at least you can make it fail (at runtime). But if that's the situation, you have bigger problems.
Sean Owen
+1  A: 

If you're making a singleton, enums are the best way to go:

public enum MySingleton {
    INSTANCE;
    // add methods & stuff here
}

// Usage:
MySingleton.INSTANCE.doSomething();

The "singletonicity" is guaranteed by the JVM - there'll only be one instance.

gustafc