Ken,
I'm not sure if the example of using a variable with a static{...}
block has the same effect as simply declaring the variable. Presumably
it is different, but the JDK could be too smart for its own good.
Regarding a recommendation, this is more difficult. Kedar's email
suggests that he thinks it might not be a problem...or might be.
My assumption is that in a highly modular system, users expect to be
able to swap out modules quickly and easily, and that modules might
change their constants (maybe a pool size or default port or
whatever). Will problems be rare? Probably. Will they be minor?
Possibly not. I don't know those answers.
At this point I think it boils down to developer intent: should the
value of constant 'X' be runtime-current or compile-time current? I
think in most cases one will expect runtime-currency and therefore the
get() style is more appropriate, albeit a weird change in working
habits.
Since we build most modules together, we might easily dismiss this as
an issue. But what happens when we start patching by shipping new
versions of modules that 3rd-parties depend on and/or when 3rd parties
start plugging in many different modules? I don't know, but it makes
me a bit uneasy.
Lloyd
On Mar 21, 2008, at 12:19 AM, 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.
>
> 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).
>
> 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 ??
>
> Thanks for bringing this up... this is one of those little things
> that could cause big problems. :)
>
> Ken
>
> Lloyd L Chambers wrote:
>>
>> Bill,
>>
>> Agreed...though problem with enums for management (JMX) include:
>>
>> - they require a new class that might not be available on a client
>> (across "the wire")
>> - they might not map automatically to other non-Java protocols
>>
>> At least that's my understanding.
>>
>> So for values returned across the wire through a management
>> interface, enums are an issue. A good example of this is
>> java.util.logging.Level; I ran into this problem recently working
>> with a developer on a JMX adapter.
>>
>> Lloyd
>>
>> On Mar 20, 2008, at 2:31 PM, Bill Shannon wrote:
>>> Lloyd L Chambers wrote:
>>>> In Glassfish V3 the system is highly modularized. Compiling one
>>>> module against another might mean using static constants eg:
>>>> // module B using org.glassfish.foo.bar from another module A
>>>> import org.glassfish.foo.bar.CONSTANT1;
>>>> ...
>>>> doSomething( CONSTANT1 );
>>>> ...
>>>> If I understand correctly, java constants are compiled into the
>>>> resulting bytecode.
>>>> So if the constant is later changed in the defining module, code
>>>> compiled against that module does *not* pick up the new value
>>>> unless it is recompiled.
>>>> In short, in a modular system, should constant values be fixed at
>>>> compile time, or picked up dynamically at runtime? If they are
>>>> to be dynamic, then our constants need to be written as methods eg:
>>>> public static String getCONSTANT1();
>>>> *not*
>>>> public static final String CONSTANT1 = "val"
>>>> Of course, there might not be a hard and fast rule. But if a
>>>> module is newly-built and has new values for its constants, it
>>>> might be reasonable to expect dependent modules to use the new
>>>> values.
>>>
>>> Yes, we should all understand this. Primitives and String constants
>>> are stored by *value*, not name. Once you choose a value for one of
>>> these constants in a public API (across module boundaries), you're
>>> committing to it, no matter what name you might use.
>>>
>>> Many of these constants should probably be enums, which don't have
>>> this
>>> problem.
>>>
>>> String constants should really only be used for things that are
>>> externally
>>> defined and really won't change. Otherwise, if it can change,
>>> it's not
>>> really a constant! :-)
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>>
>>
>> ---
>> Lloyd L Chambers
>> lloyd.chambers_at_sun.com
>> Sun Microsystems, Inc
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>
---
Lloyd L Chambers
lloyd.chambers_at_sun.com
Sun Microsystems, Inc