Java Switch Statememt - 使用抽象类中的公共(public)枚举需要常量表达式

标签 java android enums switch-statement

我已经编写了代码,使用我在 websockets 之上为创建 Android 应用程序的项目设计的协议(protocol)。

我有一个使用 Autobahn 库 weCommunicationManager 处理 websocket 通信的类。

我有许多变量和标签,它们需要用于处理从我的服务器通过 websockets 发送到应用程序的接收到的 JSON 消息。

为了将事物分开并放在一个地方,我创建了一个抽象类 ExICSProtocol,它将标签作为公共(public)静态成员保存,以便可以在任何需要的地方引用它们。

在接收到的消息中有一个消息类型的整数值,我需要能够打开它来定义如何处理该特定接收到的消息。

为此,我在 ExICSProtocol 类中实现了一个公共(public)枚举,如下所示,

public static enum MESSAGE_TYPE{
    PROTOCOL_HANDSHAKE(0),
    USER_CONNECTED(1),
    USER_DISCONNECTED(2),
    SYSTEM_STATE(3),
    CHANGE_ROOM(4),
    EXAM_START(5),
    EXAM_PAUSE(6),
    EXAM_STOP(7),
    EXAM_XTIME(8),
    SEND_MESSAGE(9),
    SUCCESS(69),
    FAILURE(-1),
    TERMINATE_CONNECTION(-2);

    private int code;

    MESSAGE_TYPE(int code){
        this.code = code;
    }

    public int getCode(){
        return this.code;
    }
}

我正尝试在 wsCommunicationManager 代码中使用它,如下所示,

private static void handleMessage(String message){
    try{
        JSONObject messageObject = new JSONObject(message);
        JSONObject messageHeader = messageObject.getJSONObject(ExICSProtocol.TAG_HEADER);
        JSONObject messagePayload = messageObject.getJSONObject(ExICSProtocol.TAG_PAYLOAD);

        int messageType = messageHeader.getInt(ExICSProtocol.TAG_MESSAGE_TYPE);


        switch(messageType){
            case ExICSProtocol.MESSAGE_TYPE.PROTOCOL_HANDSHAKE.getCode():
                //DO SOMETHING HERE
                break;

            ...

            default:
                throw new ExICSException("Unknown Message Type Received");
                break;
        }
    }catch (JSONException e){
        Log.e(TAG, "Failed to parse received message " + message, e);
    }catch (ExICSException e){
        Log.e(TAG, "Excaption Handling Message Occurred", e);
    }
}

我在 ExICSProtocol.MESSAGE_TYPE.PROTOCOL_HANDSHAKE.getCode(): 下收到错误标记,表示需要常量表达式。然而,这应该是不变的吗?

我尝试了几种不同的方法,将枚举移动到使用它的类中;同样的问题。使枚举持有的私有(private)整数公开,以便可以直接访问它;同样的问题。

我见过很多在 switch 语句中使用枚举的例子,但并不完全像我这样。我是不是在我的声明或初始化中遗漏了什么,或者我正在尝试做一些不起作用的事情。

我知道有一些相对简单的解决方法,例如将数字类型代码定义为 public static final int,但我希望尽可能将类型代码放在 MESSAGE_TYPE 下。

最佳答案

如您所见,调用方法不算作 constant expression .

更清洁的解决方案 (IMO) 是在您的枚举中有一个静态方法:

// Enum renamed to comply with conventions
public enum MessageType {

    private static final Map<Integer, MessageType> codeMap = new HashMap<>();
    // Can't do this in the constructor, as the codeMap variable won't have been
    // initialized
    static {
        for (MessageType type : MessageType.values()) {
            codeMap.put(type.getCode(), type);
        }
    }

    public static MessageType fromCode(int code) {
        return codeMap.get(code);
    }
}

然后在您的 wsCommunicationManager 代码中:

int messageCode = messageHeader.getInt(ExICSProtocol.TAG_MESSAGE_TYPE);
MessageType messageType = MessageType.fromCode(messageCode);
if (messageType == null) {
    // Unknown message code. Do whatever...
}

switch(messageType) {
    case MessageType.PROTOCOL_HANDSHAKE:
        ...
}

基本上,尽早从“面向整数”的世界进入“面向对象”的世界。这有点像尽早解析数字和基于日期的用户输入而不是传递字符串 - 只是在您的情况下代理表示是 int

关于Java Switch Statememt - 使用抽象类中的公共(public)枚举需要常量表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23808642/

相关文章:

java - 当 validator 发现表单错误时,表单页面将在 POST url 处重新显示

android - 确定 Android 上的确切屏幕翻转时间

android - 没有网络时的应用内结算 v3

struct - 访问用元组结构包装的枚举结构变体的字段

php - 如何在该类中创建类实例的常量数组?

c++ - 如何在 VS C++ 6.0 中递增枚举?

java - 字符串连接的行为方式不同

java - 为什么 RecyclerView 的 onBindViewHolder 中的 payloads 是一个列表?

java - 如果 session 不存在,如何将jsf页面重定向到主页

android - 如果 TextSize 在 android 中更多,则放置三个点