Reputation: 8904
public enum Singleton {
INSTANCE;
String fromLocation;
String toLocation;
private void initialise(String fromLocation, String toLocation) {
this.fromLocation = fromLocation;
this.toLocation = toLocation;
}
public static void main(String[] args) {
Singleton s = INSTANCE;
s.initialise(args[0],args[1]);
}
}
I can't seem to fathom the syntax to have a normal Java class constructor that I can pass args too from the main routine. The initialise routine to me seems a bad smell - but it's the best I've been able to come up with. Any suggestions?
Upvotes: 0
Views: 2351
Reputation: 1747
You're probably mean something like this:
public class Singleton {
private static Singleton instance;
public static void getInstance() {
if (instance == null)
throw new IllegalStateException("Singleton not initialized!");
return instance;
}
public static void init(String from, String to) {
if (instance != null)
throw new IllegalStateException("Singleton already initialized!");
instance = new Singleton(from, to);
}
private final String from;
private final String to;
private Singleton(String from, String to) {
this.from = from;
this.to = to;
}
}
Obviously, this is not thread-safe etc. But to be honest, you're better off using a dependecy injection framework like Spring or Guice. This Singleton.getInstance()
calls in your code are not what you want to have in the long run...
Why not use/define an enum? It says "An enum type is a special data type that enables for a variable to be a set of predefined constants." in the Java tutorial. And you are obviously not dealing with some constants.
Upvotes: 0
Reputation: 65851
The problem with your approach stems from the primary reason enum
s are so good as singletons.
Let me suggest an analogy with Schrödinger's cat thought experiment. An enum
is like the state of the cat, it is instantly completely known when the box is opened and stays that way forever. This is guaranteed by the nature of an enum
, i.e. however many people look in the box it is only the first viewer of the state of the cat that actually causes the cat to have a state. Everyone else sees an exact copy of that moment.
You therefore have two ways to install outside data into the final state of the enum
. You can either guarantee to be the one that opens the box first or - and here I stretch the analogy a little - you teach the cat to quickly reach out and grab it's state when the box first opens.
Option 1 is as complex as achieving the singleton. Being absolutely sure you are first is well nigh impossible.
So option 2 could look something like:
public enum Singleton {
INSTANCE;
final String fromLocation;
final String toLocation;
private Singleton () {
// Reach out.
this.fromLocation = App.args[0];
this.toLocation = App.args[1];
}
}
and your App
entry point looks like:
class App {
static String[] args;
public static void main(String args[]) {
App.args = args;
}
}
There are dire warnings here. Firstly, every app that uses your singleton will break if you do not start it at App.main
. Secondly, if you access your singleton anywhere in your App
class, it will probably break.
Upvotes: 1
Reputation: 49197
No, the way enum
constructors work is by
public enum Singleton {
A("from", "too"),
B("from2", "too2");
private String from, to;
private Singleton(String from, String too) {
this.from = from;
this.too = too;
}
}
What are you really trying to achieve? Perhaps an enum
isn't what you're looking for, especially if you look to assign it values runtime.
Upvotes: 0