use relational operators in switch

2019-01-19 22:21发布

问题:

Is there a way to use relational operators (<,<=,>,>=) in a switch statement?

int score = 95;

switch(score)  {
   case (score >= 90):
      // do stuff
}

the above example (obviously) doesn't work

回答1:

No you can not.
From jls-14.11

The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs.  

Relational operators (<,<=,>,>=) results in boolean and which is not allowded.

All of the following must be true, or a compile-time error occurs:

  • Every case constant expression associated with a switch statement must be assignable (§5.2) to the type of the switch Expression.

  • No two of the case constant expressions associated with a switch statement may have the same value.

  • No switch label is null.

  • At most one default label may be associated with the same switch statement.



回答2:

This might help you if you need to do it with switch itself,

char g ='X';
            int marks = 65;
            switch(marks/10)
            {
                case 1:
                case 2:
                case 3:
                case 4: g = 'F';
                        break;
                case 5: g = 'E';
                        break;
                case 6: g = 'D';
                        break;
                case 7: g = 'C';
                        break;
                case 8: g = 'B';
                        break;
                case 9: 
                case 10: g = 'A';       
                         break;
            }
            System.out.println(g);

It works this way,

    if(marks<50)
                g='F';
            else if(marks<60)
                g='E';
            else if(marks<70)
                g='D';
            else if(marks<80)
                g='C';
            else if(marks<90)
                g='B';
            else if(marks<=100)
                g='A';


回答3:

Unfortunately NO, though you can use case fall (kind of hacky) by grouping multiple case statements without break and implement code when a range ends:

int score = 95;
switch(score) {
 ..
 case 79: System.out.println("value in 70-79 range"); break;
 case 80:
 ..
 case 85: System.out.println("value in 80-85 range"); break;
 case 90:
 case 91:
 case 92:
 case 93:
 case 94:
 case 95: System.out.println("value in 90-95 range"); break;
 default: break;
}

IMHO, using if would be more appropriate in your particular case.



回答4:

It will never work. You should understand what switch does in the first place.

It will execute the statements falling under the case which matches the switch argument.

In this case, score is an argument which is 95 but score>=90 will always evaluate to either true or false and never matches an integer.

You should use if statements instead.

Also Java doesn't allow booleans in switch cases so yea.



回答5:

Simply NO

int score = 95;

switch(score)  {
   case (score >= 90):
      // do stuff
}

You are passing a int value to switch. So the case's must be in int values, where

(score >= 90)

Turns boolean.

Your case is a good candidaate for if else



回答6:

The docs for switch-case statement state:

a switch statement tests expressions based only on a single integer, enumerated value, or String object.

So there is no boolean. Doing so would make no sence since you only have two values: true or false.

What you could do is write a method which checks the score and then returns a one of the types switch can handle

For example:

enum CheckScore {
    SCORE_HIGHER_EQUAL_90,
    ...
}


public CheckScore checkScore(int score) {
    if(score >= 90) {
        return SCORE_HIGHER_EQUAL_90;
    } else if(...) {
        return ...
    }
}

and then use it in your switch:

switch(checkScore(score))  {
   case SCORE_HIGHER_EQUAL_90:
      // do stuff
}

... Or You could just use if, else-if, else directly!



回答7:

Obviously, this is not possible as a language construct. But, just for fun, we could implement it by ourselves!

public class Switch<T, V> {

    public static interface Action<V> {
        V run();
    }

    private final T value;
    private boolean runAction = false;
    private boolean completed = false;
    private Action<V> actionToRun;

    public Switch(T value) {
        this.value = value;
    }

    static public <T, V> Switch<T, V> on(T value) {
        return new Switch<T, V>(value);
    }

    public Switch<T, V> ifTrue(boolean condition) {
        runAction |= condition;
        return this;
    }

    public Switch<T, V> ifEquals(T other) {
        return ifTrue(value.equals(other));
    }

    public Switch<T, V> byDefault(Action<V> action) {
        this.actionToRun = action;
        return this;
    }

    public Switch<T, V> then(Action<V> action) {
        if (runAction && !completed) {
            actionToRun = action;
            completed = true;
        }
        return this;
    }

    public V getResult() {
        if (actionToRun == null) {
            throw new IllegalStateException("none of conditions matched and no default action was provided");
        }
        return actionToRun.run();
    }
}

Switch accepts any value to switch on and then provides functionality to match over boolean conditions (ifTrue method) or by exact matches (ifEquals method). Providing a value to switch on is needed just for the latter feature.

After building the conditions, user invokes getResult to obtain the result.

For example, we could create a method that tells us what it thinks about our score:

String tellMeMyScore(int score) {
    return Switch.<Integer, String> on(score).byDefault(new Action<String>() {
        public String run() {
            return "really poor score";
        }
    }).ifTrue(score > 95).then(new Action<String>() {
        public String run() {
            return "you rock!";
        }
    }).ifTrue(score > 65).then(new Action<String>() {
        public String run() {
            return "not bad, not bad";
        }
    }).ifEquals(42).then(new Action<String>() {
        public String run() {
            return "that's the answer!";
        }
    }).getResult();
}

This simple test:

for (int score : new int[] { 97, 85, 66, 55, 42, 32, 4 }) {
    System.out.println(score + ": " + tellMeMyScore(score));
}

Prints out:

97: you rock!
85: not bad, not bad
66: not bad, not bad
55: really poor score
42: that's the answer!
32: really poor score
4: really poor score