Runtime constant

M

MikL

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
}
}
}
 
M

MikL

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;
}
}
}
 
R

Roedy Green

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.
 
R

Roedy Green

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.
 
M

MikL

Roedy,

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

Thanks,
Michael
 
M

MikL

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.
 
R

Roedy Green

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.
 
R

Roedy Green

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.
 
C

Chris Uppal

MikL said:
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
 
R

Roland

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_/ /__/
/ \ /_/ / \
 
A

Andrew McDonagh

MikL said:
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
 
J

jan V

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)
 
T

Thomas Hawtin

jan said:
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
 
A

Andrew McDonagh

Andrew said:
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
 
R

Roedy Green

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.
 
R

Roedy Green

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top