Home > OS >  Java: What's the difference between system property and class variable in singleton class?
Java: What's the difference between system property and class variable in singleton class?

Time:06-24

I have a singleton class that looks like this

public class Data {
    private static Data data;
    private List<String> list;
   
    private Data() {
       list = new ArrayList<>();
    }
   
    public static Data getInstance() {
         if (data == null) {
             data = new Data();
         }
         return data;
    }

    public void process() {
        //check timestamp value
        //process values from list
    }
}

I want to maintain a timestamp for when the list was last processed. However I'm trying to decide whether to use a private class variable to record it or create a system variable like System.setProperty("timestamp", System.currentTimeMillis()); and access it. My requirements are that I want to access this value only within the Data class but I am running multiple instances of another class (say DataAccessor) that uses Data.process. I want to get the latest value of timestamp irrespective of which DataAccessor instance calls Data.process but I am not sure if there are any differences between storing variables through system property vs local variables in a singleton class.

CodePudding user response:

It doesn't matter, and this is, as far as code style is concerned, deplorable already, so it seems a bit silly to worry about it.

That's not how you make a singleton

It won't actually be a singleton if you call getInstance() from multiple threads. Just write:

public class Data {
  private static final Data data = new Data();

  public static Data getInstance() {
    return data;
  }
}

What you're doing ('lazily' make the singleton instance) is double useless:

  • It's only useful in the first place if your code 'touches' the type (Data), but doesn't call getInstance(). This is rare for all singletons.
  • It's only useful if the cost of creating the instance is high. It clearly is not, here.

That's not how you name classes

Data is not very descriptive. It's almost clichéd in how non-descriptive it is. More generally a class represents an actor of sorts - it's supposed to be a noun. It should be LogStorage for example, if the point of this thing is to store logs, or even better AtmLogStorage if it's specifically representing the printroll of an ATM that logs cash it emitted. Be specific.

This isn't a good use of a singleton

It's feasible to imagine a system that is running 2 separated concepts that both need the same logging functionality.

Stateless singletons (example: java's Collections or Files classes - they don't have fields or otherwise any state that you can modify) are always fine. Stateful singletons, like this one, usually aren't. Use injection frameworks if you must.

Singletons are hard to test

When writing tests you tend to want to set up dummy versions or otherwise configure some object differently than you would at normal runtime, and you usually want to be able to repeatedly create things (to isolate tests) that, during normal runtime, is only created once. Singletons and 'I wrote a unit test' do not like each other.

So, what do you do?

Make the field - and fix everything else if you can. At least with the field you can later refactor your code and make it possible to have more than one Data (hopefully you renamed it), even if just for testing purposes. system properties:

  • Cannot be controlled (any code can read and write them - you have no control over it).
  • Are invisible state, in that most java apps do not use the sysproperty store to write data. Hence most tools aren't written to deal with it; debug tools can be set to breakpoint if someone changes a field, it's much harder to breakpoint them upon some code changing a sysproperty - requires having the java core sourcecode and setting a conditional breakpoint on the setProperty method which comes in various flavours, oof.
  • Are 'singleton' and cannot be refactored away from it, whereas a field is on its own not singleton in the slightest (the fact that there's only ever one instance of the class with this field makes it a singleton, but change that aspect and your field ceases to be one. That's good).
  • Related