如何确保switch / case语句具有使用枚举等所有选项?

问题描述 投票:-4回答:2

我想用Java创建一个switch / case语句,并确保所有的字符串都在语句中。

但是,使用简单的字符串(即NORTH,SOUTH,EAST,WEST)在Java中创建枚举很容易。

如何使用点和空格的字符串?即“这是描述”,“com.stackoverflow.ClassName”

java enums switch-statement
2个回答
1
投票

如果你问你是否可以创建一个常量有空格的enum,那么答案就是“不”。

枚举常量是普通的Java标识符,如类或变量名,因此它们不能包含空格或特殊字符。


但是,将枚举与字符串链接是不可能的?没有。 如果由于某种原因,你希望你的开关盒使用enum的可读性/简洁性,但你的输入是Strings,可以有空格,圆点,特殊字符......,那么有一种方法。

你需要扩展你的enum有一个额外的字段(让我们称之为标签)来保持这个String。 在使用enum的switch case的方法中,你可以调用findByLabel方法 返回与提供的enum对应的String

这是一个小例子类,使用你的enum值NORTH,EAST,SOUTH,WEST, 链接到不同(无效枚举命名)结构的Strings

public class EnumExample {

    enum SwitchEnum {
        NORTH   ("North star"),
        EAST    ("Eastpack rulez!"),
        SOUTH   ("https://www.southafrica.net/"),
        WEST    ("java.awt.BorderLayout.WEST");

        private final String label;
        SwitchEnum(final String label) {
            this.label = label;
        }

        @Override
        public String toString() {
            return this.label;
        }

        private static final Map<String,SwitchEnum> map;
        static {
            map = new HashMap<String,SwitchEnum>();
            for (SwitchEnum v : SwitchEnum.values()) {
                map.put(v.label, v);
            }
        }
        public static SwitchEnum findByLabel(String label) {
            return map.get(label);
        }
    }

    public static String doEnumSwitch(String enumString) {
        SwitchEnum enm = SwitchEnum.findByLabel(enumString);
        if (enm != null) {
            String enumReturn = enm.name() +" : "+ enm;
            switch (enm) {
                case NORTH:
                    return enumReturn +" - Up there.";
                case EAST:
                    return enumReturn +" - Now for sale.";
                case SOUTH:
                    return enumReturn +" - Now with 50% more elephants.";
                default:
                    return "UNHANDLED ENUM : "+ enm.name() +" - "+ enm;
            }
        } else {
            return "UNKNOWN ENUM : "+ enumString;
        }
    }

    public static void main(String[] args) {
        System.out.println(doEnumSwitch("North star"));
        System.out.println(doEnumSwitch("Eastpack rulez!"));
        System.out.println(doEnumSwitch("https://www.southafrica.net/"));
        System.out.println(doEnumSwitch("java.awt.BorderLayout.WEST"));
        System.out.println(doEnumSwitch("I only want to get out of here."));
    }
}

这输出以下内容

北:北极星 - 在那里。 EAST:Eastpack rulez! - 现在出售。 南:https://www.southafrica.net/ - 现在大象增加了50%。 UNHANDLED ENUM:WEST - java.awt.BorderLayout.WEST 身份未知:我只想离开这里。


1
投票

我认为这个问题的主要问题是,您的IDE告诉您在switch语句中缺少枚举值。并询问您是否要添加它们而不是编译器。这当然不能确保您的枚举类的用户必须使用每个值。

Joshua Bloch在他的Effective Java书中提到了一种方法(章节Emulated extensible enum using an interface,可以更改为使用此处显示的开关:Java Enum Switch。但我认为交换机解决方案不能提供所有枚举使用的完全安全性。

但是既然你想知道是否有使用字符串的解决方案,我们也可以尝试使用如下所示的函数方法:Enum Switch Functional Approach并使其适用于字符串字段而不是枚举。

这看起来如下:

public class Direction {
    private static final String NORTH = "north";
    private static final String SOUTH = "south";
    private static final String EAST = "east";
    private static final String WEST = "west";

    public interface SwitchResult {
        void NORTH();
        void SOUTH();
        void EAST();
        void WEST();
    }

    public static void switchValue(String direction, SwitchResult result){
        switch (direction){
            case NORTH:
                result.NORTH();
                break;
            case SOUTH:
                result.SOUTH();
                break;
            case EAST:
                result.EAST();
                break;
            case WEST:
                result.WEST();
                break;
        }
    }

    public static void main(String[] args) {
        String direction = "west";
        Direction.switchValue(direction, new SwitchResult() {
            @Override public void NORTH() {
                System.out.println("this time north");
            }

            @Override public void SOUTH() {
                System.out.println("this time south");
            }

            @Override public void EAST() {
                System.out.println("this time east");
            }

            @Override public void WEST() {
                System.out.println("this time west");
            }
        });
    }
}

正如您在main方法中看到的那样,如果要调用switchValue函数,则必须传递字符串和接口的实现,这样可以确保覆盖所有可能性。作为交换,代码非常冗余。如果您只对一个提供一堆String值的类具有读访问权并且您希望围绕它构建switch语句,则可以使用此方法。在其他任何地方你都应该坚持使用枚举的方法。

如果您想使用第三方工具来确保无需编写任何冗余样板代码,请查看:

  1. FindBugs SF_SWITCH_NO_DEFAULT:但这只涵盖了switch语句的默认分支。
  2. @EnumMapper:注释处理器,它在编译时检查是否处理了所有枚举常量
© www.soinside.com 2019 - 2024. All rights reserved.