flagg19
flagg19

Reputation: 1782

Implementing a class of "constants" initialized at application start not at compile time

I'm working on a Java project that uses a big class of constants like:

public final class Settings {
    public static final int PORT_1 = 8888;
    public static final int PORT_2 = 8889;
    ...
}

Now, some of the value of those constants are not available at compile time anymore so I need a way to "initialize" them at application starts (e.g. from the args[]). Once initialized there should be no way to change them. I'm not very skilled in java, how do I do this in an acceptable way?

I thought of using a singleton with something like a "one shot" set method that throws an exception if called more than one time but it seams too hacky...

Upvotes: 4

Views: 497

Answers (3)

wassgren
wassgren

Reputation: 19211

Well, using system properties is a way of doing it unless there is a huge amount of constants.

private static final String CONSTANT1 = System.getProperty("my.system.property");
private static final int CONSTANT2 = Integer.valueOf(System.getProperty("my.system.property"));

System properties are passed on the command line when starting the application using the -D flag.

If there are too many variables a static initializer can be used where a property file or similar can be read that holds the properties:

public class Constants {
    private static final String CONSTANT1 = System.getProperty("my.system.property");
    private static final int CONSTANT2 = Integer.valueOf(System.getProperty("my.system.property"));
    private static final String CONSTANT3;
    private static final String CONSTANT4;

    static {
        try {
            final Properties props = new Properties();
            props.load(
                new FileInputStream(
                        System.getProperty("app.properties.url", "app.properties")));

            CONSTANT3 = props.getProperty("my.constant.3");
            CONSTANT4 = props.getProperty("my.constant.3");
        } catch (IOException e) {
            throw new IllegalStateException("Unable to initialize constants", e);
        }
    }
}

Note that if you are using some external framework such as Spring Framework or similar there is usually a built-in mechanism for this. E.g. - Spring Framework can inject properties from a property file via the @Value annotation.

Upvotes: 2

vanje
vanje

Reputation: 10383

You can use a static initializer like this:

public final class Settings {
  public static final int PORT_1;
  public static final int PORT_2;
  ...

  static {
    // create the value for PORT_1:
    PORT_1 = ...;
    // create the value for PORT_2:
    PORT_2 = ...;
  }
}

The static initializer is executed during class loading. The final keywords on PORT_1 and PORT_2 protects them to be changed afterwards.

Upvotes: 3

Aaron Digulla
Aaron Digulla

Reputation: 328624

There is no simple way to do this in Java. One way to simulate this is to use a builder which returns an internal type (so it can write the private fields) but the internal type only has getters.

See this answer: https://stackoverflow.com/a/1953567/34088

Upvotes: 1

Related Questions