4

For example:

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

    // Private constructor suppresses
    // default public constructor
    private Singleton() {};

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

Why can't I set the INSTANCE public, and access it by Singleton.INSTANCE? What will it cause?

Max Peng
  • 2,879
  • 1
  • 26
  • 43
Paul Zhang
  • 305
  • 2
  • 7
  • Because the Instance variable you are trying to access is private. Use getInstance() method as it was public. – GnanaJeyam Nov 20 '19 at 05:27
  • 2
    It would prevent you from changing the implementation of `getInstance()` to defer the instantiation of the singleton until first needed, if you so choose. Encapsulating access in a method makes future changes easier. – Andreas Nov 20 '19 at 05:28
  • @gnanajeyam95 Did you read the question? OP knows it is `private`, and is asking if changing that to `public` would cause any issues. – Andreas Nov 20 '19 at 05:29
  • Making it `public` is essentially [implementing Singleton with an Enum](https://stackoverflow.com/questions/26285520/implementing-singleton-with-an-enum-in-java). – Elliott Frisch Nov 20 '19 at 05:30

3 Answers3

4

You technically can and in this code, it will have no effect - it will behave the same.

The reasons we use getters in general are:

  • A good habit - people will be surprised to see you access a variable directly
  • Flexibility - if you have a hundred places around the code calling the getter, it's easy enough to change the method behavior (like returning new Singleton() every time instead of accessing the static variable). Not so easy if that hundred places access the variable directly.
0

Because its good practice to encapsulate your instance in order to avoid boiler plate code and in that case you need to use static block to initialize your object which is better if you initialize your object when needed (lazy load) may be benefit of your memory usage.

ibrahimgunes
  • 131
  • 8
-1

You could technically make Singleton.INSTANCE public because it is final. However, from the perspective of the user of your API, it is not obvious that Singleton.INSTANCE is final without looking at the contents of the Singleton class, and a user might be tempted to try to reassign Singleton.INSTANCE from a different class.

Making Singleton.INSTANCE only accessible through Singleton.getInstance() makes it obvious to everyone that it is not possible to reassign the variable.

Nathaniel Jones
  • 1,829
  • 3
  • 29
  • 27
  • How is `final` less obvious than not having a setter method? There is no difference between seeing `Singleton.getInstance()` vs seeing `Singleton.INSTANCE` about the likelihood of being able to change the instance. – Andreas Nov 20 '19 at 05:31
  • @Andreas it is less obvious because it requires reading the contents of the `Singleton` class, unless you have an advanced IDE. – Nathaniel Jones Nov 20 '19 at 05:33
  • 1
    Isn't this a bit farfetched? With `Singleton.getInstance()` the user might think that they could change it with a method `Singleton.setInstance(instance)` because of the getter/setter pattern. If they tried that, they would find that `setInstance` doesn't exist. That's exactly the same as tring to assign to `Singleton.INSTANCE` and then finding that the compiler refuses because the field is `final`. – Erwin Bolwidt Nov 20 '19 at 05:36
  • @NathanielJones But it also requires reading the contents of the Singleton class to determine that there is no setter method. With an IDE, both are easy to check, so equally obvious. Without an IDE, locating the field and checking for `final` modifier is easy and fast, since you can stop scanner once you find the field, which is usually at the beginning. Detecting the *lack* of a setter method requires scanning the entire source file, so it is certainly more obvious (easier, faster) to check if field is final vs check if setter method exists. – Andreas Nov 20 '19 at 06:27
  • @NathanielJones Also, if the field isn't `final`, even if it is `private`, it can be changed by code other than setter methods, which means you need to scan all the code in the source file, not just the method signatures, so even an IDE wouldn't speed that up. A `final` field is always more obvious than lack of setter method. – Andreas Nov 20 '19 at 06:33