dev@glassfish.java.net

Re: should constants be used in a modularized system?

From: Bill Shannon <bill.shannon_at_sun.com>
Date: Fri, 21 Mar 2008 13:32:35 -0700

Ken Paulsen wrote:
>
> Lloyd, Bill and others:
>
> To make sure I understand correctly, let me see if I can repeat back
> what you're saying...
>
> If you define a constant (public static final), for example:
>
> public static final String C = "hello";
>
> ...then another class references that code, it will be contained in
> bytecode (i.e. it won't look at the orginal C). In other words, if you
> change "hello" to "goodbye" w/o recompiling all classes using C, you'll
> still have "hello" in those classes that weren't recompiled.

Correct.

> However... if you define your "constant" like this:
>
> private static String getC() { return "hello" }
> public static final String C = getC();
>
> Or even:
>
> public static final String C;
> static { C = "hello"; }
>
> Then code refering to "C" *WILL* refer back to the class instead of
> keeping it local via bytecode. This is arguably not a constant now
> (although public static final, it cannot be "inlined" by other .class
> code). In other words, if you change "hello" to "goodbye" and ONLY
> compile the class which defines C, it will still be seen in ALL classes
> referencing C (i.e. no more "hello" anywhere).

Correct.

> Is that right? And if so, what is your recommendation or design pattern
> that we should follow? It was not clear (to me) from the email
> exchange. Which if these should be preferred:
>
> * Enum
> * "public static final" initialized via a static method
> * "public static final" initialized via a static block (probably the
> same thing to the JVM??)
> * No "public static final" use static getter method instead
> * or ??

Don't use Strings for enumerated values that aren't externally defined
(e.g., in a protocol spec). Use enums.

If the constant is externally defined (e.g., MIME types, charset
names, etc.), feel free to use, e.g,

public static final String PLAIN_TEXT = "text/plain";

If the constant represents a default, and you want the ability to
change the default in the future, provide the value via a public
getDefaultFoo() method.

While the static block initializer works, I'm not sure that's ever
the right answer.

Maybe we should look at a few examples of where you run into this issue?
Some real examples might help us create and understand the general rules.