Runtime constant

Discussion in 'Java' started by MikL, Aug 16, 2005.

  1. MikL

    MikL Guest

    Hi,

    Can anyone suggest a workaround for the following problem? I have a
    constant (static, final) whose value is calculated at runtime, when the
    class is loaded. Because it isn't known at compile time, I can't use it in
    a switch statement. But I'd like to.

    public class StaticTest
    {
    public final int AAA = 1;
    public final int BBB = 5 + 7;
    public final int CCC = java.lang.String.class.getFields().length;
    // ^-- just an example method

    public void doSomething (int aIndex)
    {
    switch (aIndex)
    {
    case AAA: System.out.println("alpha"); break;
    case BBB: System.out.println("bravo"); break;
    case CCC: System.out.println("charlie"); break; // this line
    doesn't compile
    }
    }
    }
     
    MikL, Aug 16, 2005
    #1
    1. Advertising

  2. MikL

    MikL Guest

    Oops, the listing missed the "static" keywords. Correct source with the
    problem is as follows.

    public class StaticTest
    {
    public static final int AAA = 1;
    public static final int BBB = 5 + 7;
    public static final int CCC = java.lang.String.class.getFields().length;

    public void doSomething (int aIndex)
    {
    switch (aIndex)
    {
    case AAA: System.out.println("alpha"); break;
    case BBB: System.out.println("bravo"); break;
    case CCC: System.out.println("charlie"); break;
    }
    }
    }
     
    MikL, Aug 16, 2005
    #2
    1. Advertising

  3. MikL

    Roedy Green Guest

    On Tue, 16 Aug 2005 15:54:49 +1000, "MikL" <> wrote or
    quoted :

    > switch (aIndex)
    > {
    > case AAA: System.out.println("alpha"); break;
    > case BBB: System.out.println("bravo"); break;
    > case CCC: System.out.println("charlie"); break; // this line


    make AAA BBB and CCC into enum constants. Then you can define an enum
    instance function to produce the calculated int you want, perhaps with
    the value passed in to the enum constant constructor. The enum
    constants will work in a Switch.
     
    Roedy Green, Aug 16, 2005
    #3
  4. MikL

    Roedy Green Guest

    On Tue, 16 Aug 2005 15:58:12 +1000, "MikL" <> wrote or
    quoted :

    > case CCC: System.out.println("charlie"); break;


    with enum you can define a function to provide the string "charlie"
    rather than using a switch.

    Ironically you use enum because they work in switches, but when you
    are done most of your switches disappear, replaced by enum functions.
     
    Roedy Green, Aug 16, 2005
    #4
  5. MikL

    MikL Guest

    Roedy,

    I like your suggestion, but alas I'm restricted to Java 1.4 for the moment.
    I should have mentioned that.

    Thanks,
    Michael
     
    MikL, Aug 16, 2005
    #5
  6. MikL

    MikL Guest

    The example was a little plain. Instead of the System.out.println(), my
    "real" code would be running all sorts of logic -- it's not just an enum
    toString() method.
     
    MikL, Aug 16, 2005
    #6
  7. MikL

    Roedy Green Guest

    On Tue, 16 Aug 2005 16:15:06 +1000, "MikL" <> wrote or
    quoted :

    >The example was a little plain. Instead of the System.out.println(), my
    >"real" code would be running all sorts of logic -- it's not just an enum
    >toString() method.


    you can still encapsulate that logic in enum functions. Each enum
    constant can implement a different function. The switch logic
    disappears.

    I'm still hoping for a language/IDE that will let me examine enum
    logic either one enum constant at a time, or comparing all enum
    constants how they each implement a function, e.g. as if the code had
    been done with switch.

    I would like to flip back and forth between either view.

    see http://mindprod.com/projects/scid.html

    where I show a grid to demonstrate the idea.
     
    Roedy Green, Aug 16, 2005
    #7
  8. MikL

    Roedy Green Guest

    On Tue, 16 Aug 2005 16:12:39 +1000, "MikL" <> wrote or
    quoted :

    >I like your suggestion, but alas I'm restricted to Java 1.4 for the moment.
    >I should have mentioned that.


    Enums are implemented with an inner class per enum constant.

    you can do pretty well everything in 1.4 EXCEPT the switch, but you
    could do implement an ordinal function to use in switch.

    to see what I mean, write the code in 1.5, then decompile it (see
    http://mindprod.com/jgloss/decomiler.html)

    Then use that to help you implement in 1.4.
     
    Roedy Green, Aug 16, 2005
    #8
  9. MikL

    Chris Uppal Guest

    MikL wrote:

    > Can anyone suggest a workaround for the following problem? I have a
    > constant (static, final) whose value is calculated at runtime, when the
    > class is loaded. Because it isn't known at compile time, I can't use it
    > in a switch statement.


    You can't, the switch statement includes the value(s) directly in the generated
    code, and therefore cannot be postponed until runtime.

    Off the top of my head, I can't think of a workaround that would allow you to
    use a switch that wouldn't be at least as slow, unclear, and unmaintainable, as
    simply using cascaded "if"s.

    -- chris
     
    Chris Uppal, Aug 16, 2005
    #9
  10. MikL

    Roland Guest

    On 16-8-2005 7:54, MikL wrote:

    > Hi,
    >
    > Can anyone suggest a workaround for the following problem? I have a
    > constant (static, final) whose value is calculated at runtime, when the
    > class is loaded. Because it isn't known at compile time, I can't use it in
    > a switch statement. But I'd like to.
    >
    > public class StaticTest
    > {
    > public final int AAA = 1;
    > public final int BBB = 5 + 7;
    > public final int CCC = java.lang.String.class.getFields().length;
    > // ^-- just an example method
    >
    > public void doSomething (int aIndex)
    > {
    > switch (aIndex)
    > {
    > case AAA: System.out.println("alpha"); break;
    > case BBB: System.out.println("bravo"); break;
    > case CCC: System.out.println("charlie"); break; // this line
    > doesn't compile
    > }
    > }
    > }
    >
    >


    Convert your int index to an action object, which does the work for each
    constant. IIRC this is the so-called Command Pattern. I've used it in
    several occasions, both for primitive types (char, int, etc.) and
    reference type (mostly Strings, but any type could do).

    Below is an example how I'd implement it. You'll need a Map with ints as
    keys (wrapped in Integer objects), and Action instances as values. In
    the example I've chosen an interface, but Action could also be an
    (abstract) class. Your switch now works by getting an Action object from
    the Map that matches anIndex and call its method to do something.


    import java.util.HashMap;
    import java.util.Map;

    public class CommandExample {

    private static interface Action {
    public void doSomething();
    }

    public static final int AAA = 1;
    public static final int BBB = 5 + 7;
    public static final int CCC =
    java.lang.String.class.getFields().length;

    private int someInstanceField;

    private static Map actions;

    public void doSomething(int anIndex) {
    Action action = getAction(anIndex);
    if (action != null) {
    action.doSomething();
    } else {
    // default:
    }
    }

    private static Action getAction(int anIndex) {
    return (Action) getActions().get(new Integer(anIndex));
    }
    private static synchronized Map getActions() {
    // lazily create the actions Map
    if (actions == null) {

    actions = new HashMap();

    actions.put(new Integer(AAA), new Action() {
    public void doSomething() {
    System.out.println("alpha");
    }
    });

    actions.put(new Integer(BBB), new Action() {
    public void doSomething() {
    System.out.println("bravo");
    }
    });

    actions.put(new Integer(CCC), new Action() {
    public void doSomething() {
    System.out.println("charlie");
    }
    });
    }
    return actions;
    }
    }



    You can easily extend it by adding additional methods to the Action
    interface. These methods can have parameters. For instance, when you
    need to access an instance field, you could pass this to the method:

    private static interface Action {
    public void doSomething();
    public int calcSomething(CommandExample thiz);
    }


    You then would have to implement the calcSomething method for each Action:

    private static synchronized Map getActions() {
    // lazy create actions Map
    if (actions == null) {
    actions = new HashMap();
    actions.put(new Integer(AAA), new Action() {
    public int calcSomething(CommandExample thiz) {
    return thiz.someInstanceField + 1;
    }
    public void doSomething() {
    System.out.println("alpha");
    }
    });
    // ... etcetera


    Applying it would look like this:

    public int calcSomething(int anIndex) {
    Action action = getAction(anIndex);
    if (action != null) {
    return action.calcSomething(this);
    } else {
    // default:
    return 0;
    }
    }

    public static void main(String[] args) {
    CommandExample example = new CommandExample();
    example.doSomething(12);
    System.out.println(example.calcSomething(1));
    }
    --
    Regards,

    Roland de Ruiter
    ` ___ ___
    `/__/ w_/ /__/
    / \ /_/ / \
     
    Roland, Aug 16, 2005
    #10
  11. MikL wrote:
    > Hi,
    >
    > Can anyone suggest a workaround for the following problem? I have a
    > constant (static, final) whose value is calculated at runtime, when the
    > class is loaded. Because it isn't known at compile time, I can't use it in
    > a switch statement. But I'd like to.
    >
    > public class StaticTest
    > {
    > public final int AAA = 1;
    > public final int BBB = 5 + 7;
    > public final int CCC = java.lang.String.class.getFields().length;
    > // ^-- just an example method
    >
    > public void doSomething (int aIndex)
    > {
    > switch (aIndex)
    > {
    > case AAA: System.out.println("alpha"); break;
    > case BBB: System.out.println("bravo"); break;
    > case CCC: System.out.println("charlie"); break; // this line
    > doesn't compile
    > }
    > }
    > }
    >
    >



    Yep, but I don't have time right now to show the code, just a possible
    answer....

    replace the conditional logic with polymorphism....

    i.e. a map of Command objects
     
    Andrew McDonagh, Aug 16, 2005
    #11
  12. MikL

    jan V Guest

    > Ironically you use enum because they work in switches, but when you
    > are done most of your switches disappear, replaced by enum functions.


    What do you mean by an "enum function" ? (checked your glossary, you don't
    seem to have an entry for this concept)
     
    jan V, Aug 17, 2005
    #12
  13. jan V wrote:
    >>Ironically you use enum because they work in switches, but when you
    >>are done most of your switches disappear, replaced by enum functions.

    >
    > What do you mean by an "enum function" ? (checked your glossary, you don't
    > seem to have an entry for this concept)


    I assume it means an instance method that happens to be a member of an
    enum. You can't go around defining every combination of words. Although
    you can legislate against their use.

    Tom Hawitn
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Aug 17, 2005
    #13
  14. Andrew McDonagh wrote:
    > MikL wrote:
    >
    >> Hi,
    >>


    snipped
    >
    >
    > Yep, but I don't have time right now to show the code, just a possible
    > answer....
    >
    > replace the conditional logic with polymorphism....
    >
    > i.e. a map of Command objects



    Excellent, Roland has managed to provide the example code before me
    (cheers Roland)

    Andrew
     
    Andrew McDonagh, Aug 17, 2005
    #14
  15. MikL

    Roedy Green Guest

    On Wed, 17 Aug 2005 11:12:09 GMT, "jan V" <> wrote or quoted
    :

    >
    >What do you mean by an "enum function" ? (checked your glossary, you don't
    >seem to have an entry for this concept)


    check out http://mindprod.com/jgloss/enum.html

    I did a fairly major update on it late last night.

    There are there flavours of enum methods:


    1. common code for all, each uses a different constants passed in the
    constructor.

    2. all enum constants implement a common method a different way.
    Constants override an abstract method is the enum itself.

    3. some enum constants implement a method, and others do not.
     
    Roedy Green, Aug 18, 2005
    #15
  16. MikL

    Roedy Green Guest

    On Wed, 17 Aug 2005 11:12:09 GMT, "jan V" <> wrote or quoted
    :

    >What do you mean by an "enum function" ?


    an instance method defined on an enum constant or possibly a method
    defined on an enum.


    Sorry, I am old, and ancient terminology creeps through from time to
    time. At least I have stopped myself from referring to RAM as "core".

    The neat thing about enums you can nearly always get rid of switch
    code by defining an enum constant instance method. This consolidates
    logic in the enum class where it is easier to maintain, and it
    simplifies client logic.
     
    Roedy Green, Aug 18, 2005
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christopher M. Lusardi
    Replies:
    1
    Views:
    4,094
  2. Martin Magnusson
    Replies:
    2
    Views:
    508
    John Harrison
    Oct 8, 2004
  3. Tor Erik Soenvisen
    Replies:
    14
    Views:
    564
    Tim Roberts
    Nov 23, 2006
  4. Replies:
    4
    Views:
    339
    Keith Thompson
    Dec 14, 2006
  5. Replies:
    13
    Views:
    12,930
    Kai-Uwe Bux
    Jan 22, 2007
Loading...

Share This Page