I would like to know if there is a way to execute a procedure at the end of each passage through a switch/case operator in Java ? (In the case of a switch in a loop for example)
Something like this 'after' operator (which do :
switch (constant) {
case a: return "x";
case b: return "y";
case c: return "z";
default: return "unknown";
after: alwayPassInThisMethodAfterBreakStatement()
}
I can't simply write my operation after the switch case statement because of the 'return' operation and I can't use a 'break' operation instead of 'return' because of my context.
You can use try-finally to guarantee the after method is called, and this avoids repeating the call per branch. Example:
try {
switch (constant) {
case 1: return "x";
case 2: return "y";
case 3: return "z";
default: return "unknown";
}
} finally {
alwaysCalledAtEnd();
}
There is no after or finally in a switch-case statement. You could build an if-else like:
if(yourvar==a) {
Alwaysmethod();
return x;
} else if(yourvar==b) {
Alwaysmethod();
return y;
} else if(yourvar==c) {
Alwaymethod();
return z;
} ..
But this makes no sense. You could put the method just after your switch-case or wherever your return arives so it would always be executed.
public class Hello {
public static void main(int a) {
switch (a) {
case 1:
System.out.println("Hi");
}
switch (a) {
case 2:
System.out.println("Hello");
}
}
}
Hi,
I want to know if it is possible for me to use Switch Case for the same variable twice, like I've done in the snippet attached.
Thanks.
The code you have provided works. So long as the variable a is in scope, you can use it for as many switch statements as you like.
If you want to check for multiple values of a in the same switch, then you should use different cases. E.g.:
switch (a) {
case 1:
System.out.println("a was 1");
break; // if we did not break, then execution would "fall-through" to the next case
case 2:
System.out.println("a was 2");
break;
default:
System.out.println("a was not 1 or 2");
}
Find out more about the switch statement in the Java Documentation.
I know you can have something like
public enum letters{
A, B, C, D
}
then have something like with each letter having its own class with a method
switch(letters)
case A:
A.methodA();
break;
case B:
B.methodB();
break;
case C:
C.methodC();
break;
case D:
D.methodD();
break;
default:
System.out.println("Learn the alphabet");
but can you have something like
switch(listOfLetterEnums)
...
In my program I turn command line enum arguments into a list and I need to know how to run each of the enums' method from that list whether it be a switch statement or something else.
I should add when I try it I get an error saying "cannot convert List. Only convertible int values or enum variables" would converting to a list of enums work if the above is possib
You will need to put a for loop around the switch statement to parse each element of the list separately. If the list is an Iterable then it should look something like this:
for (letterEnum : listOfLetterEnums) {
switch(letterEnum) {
...
}
}
For this to work, your list will need to implement the Iterator interface or extend a class which implements it. In this case you probably want to extend ArrayList.
If the list is an array you can just parse each element of the array:
for (int i = 0; i < listOfLetterEnums.length; i++) {
switch(listOfLetterEnums[i]) {
...
}
}
public class Test {
private enum Foo {
ABC, DEF;
}
public static void main(String... args) {
List<Foo> myfoos = new ArrayList<Foo>();
myfoos.add(Foo.ABC);
for(Foo i:myfoos)
switch (i) {
case ABC:
System.out.println("do abc");
break;
case DEF:
System.out.println("do def");
break;
}
}
}
You need to loop over the list, and switch based on the value.
letters[] listOfLetterEnums = { letters.A, letters.B, letters.C, letters.D };
for(letter let : listOfLetterEnums)
{
switch(let)
{
case A:
A.methodA();
break;
case B:
B.methodB();
break;
case C:
C.methodC();
break;
case D:
D.methodD();
break;
default:
System.out.println("Learn the alphabet");
}
}
I have the below piece of code that I have developed ..
public byte determineCardType(final IInput inputData) {
byte cardType = UNKNOWN_CARD;
try {
if (isWagRewardsLoyaltyCard(inputData))
cardType = WAG_LOYALTY_CARD_TYPE;
else if (isDRCard(inputData)) //checking that card scanned and swiped is a DR Card
cardType = DR_CARD_TYPE;
else if (isWagRewardsPartnerCard(inputData))
cardType = AARP_CARD_TYPE;
return cardType;
} catch (Exception e) {
return UNKNOWN_CARD;
}
}
please advise me can the above code can be adjusted in switch loop, if yes then please advise, Thanks in advance.
the other code that is linked to it...
if((aarpCardSupport.isAARPCard(input))||(determineCardType(input)==DR_CARD_TYPE)) {
return true;
} else if((isDRCard(input))&&(isDRLoayltyEnabled())) { //would return 1 for DR card only when isDRLoayltyEnabled returns true
return true;
}
return false ;
Switch won't help you, but conditional expressions can:
return isWagRewardsLoyaltyCard(inputData) ? WAG_LOYALTY_CARD_TYPE
: isDRCard(inputData) ? DR_CARD_TYPE
: isWagRewardsPartnerCard(inputData) ? AARP_CARD_TYPE
: UNKNOWN_CARD;
I would strongly recommend against catching Exception, btw. Catch specific exception types if you must - although in that case I'd at least log the error before returning.
EDIT: As for the second piece of code, it looks like you just want:
return aarpCardSupport.isAARPCard(input)
|| determineCardType(input) == DR_CARD_TYPE
|| (isDRCard(input) && isDRLoayltyEnabled);
Although why determineCardType(input) would return something other than DR_CARD_TYPE when isDRCard(input) returns true is a mystery...
Don't do it. If you must do it, you could do it like this:
public byte determineCardType (final IInput inputData) {
byte cardType = UNKNOWN_CARD;
try {
switch (isWagRewardsLoyaltyCard (inputData) ? 1 :
(isDRCard (inputData) ? 2 : (isWagRewardsPartnerCard (inputData) ? 3 : 4)))
{
case 1: cardType = WAG_LOYALTY_CARD_TYPE; break;
case 2: cardType = DR_CARD_TYPE; break;
case 3: cardType = AARP_CARD_TYPE; break;
default: // UNKNOWN_CARD already default
}
return cardType;
} catch (CardException ce) {
return UNKNOWN_CARD;
}
}
}
But since you return a cardType as byte, you can switch later, after setting the type. This code is harder to read than your code. Jons code is at least lean.
I see you're new to switch statements. So I elaborate a little.
A switch statement is useful if your input is in Integral form (int, byte, short, Enum), and if you can match it against a - mostly medium short list of values.
And if you otherwise would use a sequence of if/else statements. Case statements needn't be mutual exclusive, but most times they are.
In your case, you call 3 methods which return booleans, so the input isn't integral. But your output is.
Later in the code, you could write:
byte cardType = determineCardType (inputDate);
switch (cardType)
{
case WAG_LOYALTY_CARD_TYPE: doWlct (foo, bar); break;
case DR_CARD_TYPE: doDct (); break;
case AARP_CARD_TYPE: doAct (baz); foobar (); break;
case UNKNOWN_CARD: System.err.println ("Unknown card");
}
Else you would have to write:
if (cardType == WAG_LOYALTY_CARD_TYPE)
doWlct (foo, bar);
else if (cardType == DR_CARD_TYPE)
doDct ();
else if (cardType == AARP_CARD_TYPE) {
doAct (baz);
foobar ();
}
else ...
Since Java 1.7 switch over Strings is possible as well, but until then, you could only switch over integral types, and the case labels have to be literally constant and known at compile time.
In OOP, switch statements are often abandoned in favor of dynamic dispatch.
interface Card {
public abstract int authenticate ();
}
class WagLoyalityCard implements Card {
public int authenticate () {
doWlct (foo, bar);
}
}
class DrCard implements Card {
public int authenticate () {
doDct ();
}
}
// ... and so on
Card card = new DrCard ();
// authenticate:
card.authenticate ();
// depending on the card type, DrCard.authenticate () or
// WagCard.authenticate () gets called.
I need to change the following if's to a switch-case while checking for a String, to improve the cyclomatic complexity.
String value = some methodx;
if ("apple".equals(value)) {
method1;
}
if ("carrot".equals(value)) {
method2;
}
if ("mango".equals(value)) {
method3;
}
if ("orange".equals(value)) {
method4;
}
But I am not sure what value I'm going to get.
Java (before version 7) does not support String in switch/case. But you can achieve the desired result by using an enum.
private enum Fruit {
apple, carrot, mango, orange;
}
String value; // assume input
Fruit fruit = Fruit.valueOf(value); // surround with try/catch
switch(fruit) {
case apple:
method1;
break;
case carrot:
method2;
break;
// etc...
}
Everybody is using at least Java 7 now, right? Here is the answer to the original problem:
String myString = getFruitString();
switch (myString) {
case "apple":
method1();
break;
case "carrot":
method2();
break;
case "mango":
method3();
break;
case "orange":
method4();
break;
}
Notes
The case statements are equivalent to using String.equals.
As usual, String matching is case sensitive.
According to the docs, this is generally faster than using chained if-else statements (as in cHao's answer).
Learn to use else.
Since value will never be equal to two unequal strings at once, there are only 5 possible outcomes -- one for each value you care about, plus one for "none of the above". But because your code doesn't eliminate the tests that can't pass, it has 16 "possible" paths (2 ^ the number of tests), of which most will never be followed.
With else, the only paths that exist are the 5 that can actually happen.
String value = some methodx;
if ("apple".equals(value )) {
method1;
}
else if ("carrot".equals(value )) {
method2;
}
else if ("mango".equals(value )) {
method3;
}
else if ("orance".equals(value )) {
method4;
}
Or start using JDK 7, which includes the ability to use strings in a switch statement. Course, Java will just compile the switch into an if/else like construct anyway...
To reduce cyclomatic complexity use a map:
Map<String,Callable<Object>> map = new HashMap < > ( ) ;
map . put ( "apple" , new Callable<Object> () { public Object call ( method1 ( ) ; return null ; } ) ;
...
map . get ( x ) . call ( ) ;
or polymorphism
Just to make concrete emory's answer, the executable code is the following :
Map<String,Callable<USer>> map = new HashMap<String,Callable<User>>();
map.put( "test" , new Callable<User> () { public User call (){ return fillUser("test" ); }} ) ;
map.put( "admin" , new Callable<Utente> () { public Utente call (){ return fillUser("admin" ); }} ) ;
where user is a POJO, and then
User user = map.get(USERNAME).call();
finally the called method is somewhere :
private User fillUser(String x){
User user = new User();
// set something in User
return user;
}
Java does not support Switch-case with String. I guess this link can help you. :)
Here is a possible pre-1.7 way, which I can't recommend:
public class PoorSwitch
{
final static public int poorHash (String s) {
long l = 0L;
for (char c: s.toCharArray ()) {
l = 97*l + c;
}
return (int) l;
}
public static void main (String args[])
{
String param = "foo";
if (args.length == 1)
{
param = args[0];
}
// uncomment these lines, to evaluate your hash
// test ("foo");
// test ("bar");
switch (poorHash (param)) {
// this doesn't work, since you need a literal constant
// so we have to evaluate our hash beforehand:
// case poorHash ("foo"): {
case 970596: {
System.out.println ("Foo!");
break;
}
// case poorHash ("bar"): {
case 931605: {
System.out.println ("Bar!");
break;
}
default: {
System.out.println ("unknown\t" + param);
break;
}
}
}
public static void test (String s)
{
System.out.println ("Hash:\t " + s + " =\t" + poorHash (s));
}
}
Maybe you could work with such a trick in a generated code. Else I can't recommend it. Not so much that the possibility of a hash collision makes me worry, but if something is mixed up (cut and paste), it is hard to find the error. 931605 is not a good documentation.
Take it just as proof of concept, as curiosity.
We can apply Switch just on data type compatible int :short,Shor,byte,Byte,int,Integer,char,Character or enum type.
Evaluating String variables with a switch statement have been implemented in Java SE 7, and hence it only works in java 7. You can also have a look at how this new feature is implemented in JDK 7.
Java 8 supports string switchcase.
String type = "apple";
switch(type){
case "apple":
//statements
break;
default:
//statements
break; }
String name,lname;
name= JOptionPane.showInputDialog(null,"Enter your name");
lname= JOptionPane.showInputDialog(null,"Enter your father name");
if(name.equals("Ahmad")){
JOptionPane.showMessageDialog(null,"welcome "+name);
}
if(lname.equals("Khan"))
JOptionPane.showMessageDialog(null,"Name : "+name +"\nLast name :"+lname );
else {
JOptionPane.showMessageDialog(null,"try again " );
}
}}
Not very pretty but here is another way:
String runFct =
queryType.equals("eq") ? "method1":
queryType.equals("L_L")? "method2":
queryType.equals("L_R")? "method3":
queryType.equals("L_LR")? "method4":
"method5";
Method m = this.getClass().getMethod(runFct);
m.invoke(this);
String value = someMethod();
switch(0) {
default:
if ("apple".equals(value)) {
method1();
break;
}
if ("carrot".equals(value)) {
method2();
break;
}
if ("mango".equals(value)) {
method3();
break;
}
if ("orance".equals(value)) {
method4();
break;
}
}