Java开关语句的多种情况

我只是想弄清楚如何在Java开关语句中使用许多多个案例。下面是我想做的一个例子。

switch (variable)
{
    case 5..100:
        doSomething();
    break;
}

与不得不做的事相比。

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}

有什么想法,这是否可行,或有什么好的替代方案?

解决办法

遗憾的是,这在Java中是不可能的。你将不得不使用if-else语句。

评论(16)

第二个选项是完全可以的。 我不知道为什么有回答者说这是不可能的。 这很好,我一直在这样做。

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}
评论(6)

一个面向对象的选择是使用 "责任链模式 "对决策进行建模,以取代过大的 "开关 "和 "if/else "结构。

责任链模式

责任链模式 允许将一个请求的源头与决定该请求的人分开。 职责链模式允许将一个请求的源头与决定哪一个请求的源头分开。 潜在的大量处理程序。 哪些处理者应该对该请求采取行动。代表链式角色的 代表链角色的>类 代表链角色的>类将请求从源头 的请求沿着处理程序的列表传导,直到有一个 处理程序接受请求并 对其采取行动。

下面是一个使用泛型的实例实现,它也是类型安全的。

import java.util.ArrayList;
import java.util.List;

/**
* Generic enabled Object Oriented Switch/Case construct
* @param  type to switch on
*/
public class Switch
{
    private final List cases;

    public Switch()
    {
        this.cases = new ArrayList();
    }

    /**
     * Register the Cases with the Switch
     * @param c case to register
     */
    public void register(final Case c) { this.cases.add(c); }

    /**
     * Run the switch logic on some input
     * @param type input to Switch on
     */
    public void evaluate(final T type)
    {
        for (final Case c : this.cases)
        {
            if (c.of(type)) { break; }
        }
    }

    /**
     * Generic Case condition
     * @param  type to accept
     */
    public static interface Case
    {
        public boolean of(final T type);
    }

    public static abstract class AbstractCase implements Case
    {
        protected final boolean breakOnCompletion;

        protected AbstractCase()
        {
            this(true);
        }

        protected AbstractCase(final boolean breakOnCompletion)
        {
            this.breakOnCompletion = breakOnCompletion;
        }
    }

    /**
     * Example of standard "equals" case condition
     * @param  type to accept
     */
    public static abstract class EqualsCase extends AbstractCase
    {
        private final T type;

        public EqualsCase(final T type)
        {
            super();
            this.type = type;
        }

        public EqualsCase(final T type, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.type = type;
        }
    }

    /**
     * Concrete example of an advanced Case conditional to match a Range of values
     * @param  type of input
     */
    public static abstract class InRangeCase extends AbstractCase
    {
        private final static int GREATER_THAN = 1;
        private final static int EQUALS = 0;
        private final static int LESS_THAN = -1;
        protected final T start;
        protected final T end;

        public InRangeCase(final T start, final T end)
        {
            this.start = start;
            this.end = end;
        }

        public InRangeCase(final T start, final T end, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.start = start;
            this.end = end;
        }

        private boolean inRange(final T type)
        {
            return (type.compareTo(this.start) == EQUALS || type.compareTo(this.start) == GREATER_THAN) &&
                    (type.compareTo(this.end) == EQUALS || type.compareTo(this.end) == LESS_THAN);
        }
    }

    /**
     * Show how to apply a Chain of Responsibility Pattern to implement a Switch/Case construct
     *
     * @param args command line arguments aren't used in this example
     */
    public static void main(final String[] args)
    {
        final Switch integerSwitch = new Switch();
        final Case case1 = new EqualsCase(1)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.type.equals(type))
                {
                    System.out.format("Case %d, break = %s\n", type, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        integerSwitch.register(case1);
        // more instances for each matching pattern, granted this will get verbose with lots of options but is just
        // and example of how to do standard "switch/case" logic with this pattern.
        integerSwitch.evaluate(0);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(2);

        final Switch inRangeCaseSwitch = new Switch();
        final Case rangeCase = new InRangeCase(5, 100)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.inRange(type))
                {
                    System.out.format("Case %s is between %s and %s, break = %s\n", type, this.start, this.end, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        inRangeCaseSwitch.register(rangeCase);
        // run some examples
        inRangeCaseSwitch.evaluate(0);
        inRangeCaseSwitch.evaluate(10);
        inRangeCaseSwitch.evaluate(200);

        // combining both types of Case implementations
        integerSwitch.register(rangeCase);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(10);

    }
}

这只是我在几分钟内完成的一个快速草图,更复杂的实现可能允许将某种 "命令模式 "注入到 "案例 "的实现实例中,使其更像一个回调的IoC风格。

这种方法的好处是,Switch/Case语句都是关于副作用的,这种方法将副作用封装在类中,因此可以更好地管理和重用它们,它最终更像是功能语言中的模式匹配,这并不是一件坏事。

我将在Github上发布这个Gist的任何更新或改进。

评论(1)