I was unable to find a prior question like this here (which surprises me), so..
I have a working Java program where part of it analyzes typed input. Some input 'options' are the strings in the cases below.
switch (varName.toLowerCase()) {
case "steps":
common.steps = true;
break;
case "scale":
common.scale = true;
break;
case "float":
common.fracts = false;
break;
case "fraction":
common.fracts = true;
break;
case "spaces":
common.spaces = false;
break;
... etc.
}
In C or C++, I could shorten this code by making a list (which is a structure containing a string name and a variable pointer) such as
LIST varAction[] = { { "steps", &common.steps },
{ "scale", &common.scale },
.. etc.
};
and then simply checking in a loop with i = 0 thru size of the list
if ( strcmp(varAction[i].name, input) == 0) {
*varAction[i].pointer = condition;
}
The Java switch occurs more than once and is a maintenance problem, which is why I want a better way.
I could use a hashed index into an array using the hash of the string, but that would prevent me from using the specific variable names thru the code as needed, making that code less clear... i.e. I don't want to do (pseudo-code)
hashTable[varName] instead of (for example)
if ( common.fracts )
{ do something }
There must be a better way? Is there? Thanks in advance.
conditional statements - Alternative to Switch Case in Java - Stack Overflow.
The switch can includes multiple cases where each case represents a particular value. Code under particular case will be executed when case value is equal to the return value of switch expression. If none of the cases match with switch expression value then the default case will be executed.
You can't because the language doesn't work that way.
From your question, it's fairly clear that you know you can't do what you've said you'd do in C/C++, but just for others coming to the question: Java doesn't have references to variables.
It's tempting to push the question out a level: Look at why you have varName
in the first place and see if you can avoid it.
The Java switch occurs more than once and is a maintenance problem, which is why I want a better way.
That suggests that common
should have accessor function(s) for this information, so the switch exists only in one place (the getter) or two places (the getter and the setter).
void setThingy(String name, boolean value) {
switch (name.toLowerCase()) {
case "steps":
this.steps = value;
break;
case "scale":
this.scale = value;
break;
case "float":
this.fracts = value;
break;
case "fraction":
this.fracts = value;
break;
case "spaces":
this.spaces = value;
break;
// ... etc.
}
}
boolean getThingy(String name) {
switch (name.toLowerCase()) {
case "steps":
return common.steps;
case "scale":
return common.scale;
case "float":
return this.fracts;
case "fraction":
return this.fracts;
case "spaces":
return this.spaces;
// ... etc.
}
}
If common
's class isn't something you can change, a static utility function somewhere would also work, but better if it's in the class if possible.
With Java 8+ you could use something like:
Map<String, Runnable> actions = new HashMap<> ();
actions.put("steps", () -> common.steps = true);
actions.put("scale", () -> common.scales = true);
//etc.
then in your code:
actions.get(varName.toLowerCase()).run(); //need null check
You could do it with Java 7- too using anonymous classes but it would be more verbose.
Here’s an option, developing my idea from the comment just a little bit. Not sure whether you will like it, I’d like to offer it in case.
public class Common {
private Map<String, Boolean> options = new HashMap<>();
public void setOption(String varName, boolean condition) {
options.put(varName.toLowerCase(), condition);
}
public boolean isSteps() { return options.get("steps"); }
public boolean isFracts() { return options.get("fractions"); }
public boolean isScale() { return options.get("scale"); }
}
You may want to put in some defense, for instance to avoid setting non-existing options.
Edit: Drawing on David Foerster’s comments on enums, here’s a solution using them:
public enum Option {
steps, scale, fraction;
private boolean option = false;
public static void setOption(String varName, boolean condition) {
valueOf(varName.toLowerCase()).option = condition;
}
public boolean isSet() {
return option;
}
}
Now the lookup happens in the setter, not in the getter. Defence against setting non-existing options is built-in: you will get an exception if you try, this behaviour can of course be modified if you prefer. The solution is quite extensible, it’s easy to add more enum constants if the need arises.
Warning: It's been a while since I last wrote some Java, and this is probably against best practices, so continue with care! Also it's just a quick and dirty example, I wrote this on a (not up to date) mobile phone...
You could try to use reflection:
class Common {
public boolean a;
public boolean b;
public boolean tryToSet(String field, boolean value) throws java.lang.Exception {
Class<?> cl = this.getClass();
try {
Field f = cl.getDeclaredField(field);
f.setBoolean(this, value);
return true;
} catch(NoSuchFieldException e) {
return false;
}
}
}
Returning a boolean gives you the possibility to implement a "default case":
if (! c.tryToSet("x", false)) {
System.out.println("some default case");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With