views:

160

answers:

2

I use around 1000 properties associated with a specific java.util.Properties which is backed by a file. The main reason for the file is to change them without recompiling the program and to allow users to adjust their according to their taste. Some of the properties are used only in one place in the code, but there are some properties that are used several times in different segments of code and even different classes.

I have recently got the habit of declaring all those properties that are used as a String constants, usually in a seperate interface like this:

public interface AnimalConstants {
  public static final String WEIGHT_PROPERTY = "weight";
  public static final String RUNNING_SPEED_PROPERTY = "speedInKph";
  public static final String HOURS_OF_SLEEP_A_DAY_PROPERTY = "sleepHrs";
  ...
}

When a class need to access some of the animal properties, I just implement this interface and I have access to all those property constants declared. When I need a specific property I just use the corresponding constant, without thinking what is its exact name (since abbreviations are used often) and, what is more important, the risk of mistyping a property name is eliminated this way. Another advantage is that if I later choose to rename a property to make it more clear to the advanced user who configures those properties), I just need to change that name in the interface where that property constant is declared (and of course the property file), so no need to "search and replace" the entire project. Finally, I can easily check whether the property is being used or not; I just comment it, compile the code and see if there is an error.

However, in spite of all these advantages, I am curious what are the disadvantages of this approach. What interests me the most is the following:

  • What impact has this approach (1000 String constants) on the String pool? Or they are created on-demand when I access those constants? Does this prevent other Strings from being cached in the String pool?
  • What is the performance cost of this approach compared to the one where I use hard-coded String constants, is it the same (neglecting the cost of accessing field)? Does the String pool behave similarly or a lot different?
  • What's the average memory increase with this approach, are all those String constants kept in memory all the time?

Any good comment/observation is welcome.

+5  A: 

Static fields are are initialized during the initialization phase during class loading.

But if a primitive type or a String is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value. This is when String Literals for unique string's will be created which are defined as values of constants.

But it is similar as loading constants from resources in Properties object (writing code for same). Constants definitely consume memory. String pool behavior wont change.

Some thought on design approach:

It is very easy to put all configuration constants in a class, then refer to them throughout the app. To change the static configuration constants you modify the source and recompile. What if at some point in future, your program needs maintain more than one configuration, or to alternate between configurations as it processes different files, or even runs one thread with one configuration and another thread with a different configuration. You won’t be able to use that technique. So for better designs you store constants which never change as static constants in Class definition.These are loaded as soon as Class is loaded in memory. In other case which i described earlier (Resource loading) you keep these in various properties files which can be loaded in JAVA Properties object. Examples for such cases can be JDBC connection related information, etc...

YoK
Do you mean that I need only to change interface to class and that's it?And I don't understend what do you mean by "changing different configurations", if you could please explain a bit more or give a short example?
leden
There can be situation where configurations can differ as per deployment. DB is an good example for same. Per deployment db servers can be of different types (oracle,sqlserver ) as well as base details can change like server ip,user,pass etc.
YoK
@Yok please explain what "Static constants defined in class are loaded as soon as Class is loaded by JVM" means.
naikus
@naikus edited and updated my answer with additional details.
YoK
@Yok I think the first sentence is misleading. It should be: Static fields are are initialized during the initialization phase during class loading.
naikus
@naikus updated my answer.
YoK
@Yok Much better +1
naikus
+2  A: 

1) What impact has this approach (1000 String constants) on the String pool?

Declaring property names as String constants is the right decision. But there will be no change in the 'String Literal Pool'. When multiple instances of the same literal present, all of them are simply linked to same item in the literal pool (provided String constructor is not used).

2) they are created on-demand when I access those constants?

String literals are added to 'String Literal Pool' during class loading.

3) Does this prevent other Strings from being cached in the String pool?

No.

4) What is the performance cost of this approach compared to the one where I use hard-coded String constants, is it the same (neglecting the cost of accessing field)? Does the String pool behave similarly or a lot different?

It is the same.

5) What's the average memory increase with this approach, are all those String constants kept in memory all the time?

I have already answered. :)

Additional notes

a) Constants interface is a Java anti-pattern. Please avoid it.

b) You must read this Javaranch article.

Sujee