簡體   English   中英

Java Switch Statememt - 使用抽象類的公共枚舉所需的常量表達式

[英]Java Switch Statememt - Constant Expression Required Using Public Enum from Abstract Class

我編寫的代碼使用了我在webockets上設計的協議,用於創建Android應用程序的項目。

我有一個使用Autobahn庫weCommunicationManager處理websocket通信的類。

我有許多變量和標簽,用於處理從我的服務器通過websockets到應用程序的收到的JSON消息。

為了使事物分離並在一個地方,我創建了一個抽象類ExICSProtocol ,它將標記保存為公共靜態成員,以便可以在必要時引用它們。

在收到的消息中是消息類型的整數值,我需要能夠打開它來定義如何處理該特定的接收消息。

為此,我在ExICSProtocol類中實現了一個公共枚舉,如下所示,

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():下標記錯誤ExICSProtocol.MESSAGE_TYPE.PROTOCOL_HANDSHAKE.getCode():說需要一個常量表達式。 然而,這應該是不變的?

我嘗試了一些不同的東西,將枚舉移動到正在使用它的類中; 同樣的問題。 使enum公共持有私有int,以便可以直接訪問; 同樣的問題。

我已經看到很多在switch語句中使用枚舉的例子,但非常像我。 我在聲明或初始化中遺漏了什么,或者我正在嘗試做一些無效的事情。

我知道有相對簡單的解決方法,例如將數字類型代碼定義為公共靜態最終整數,但我希望在可能的情況下將類型代碼保存在MESSAGE_TYPE下。

正如您所見,調用方法不算作常量表達式

更清潔的解決方案(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

你可以在你的MESSAGE_TYPE枚舉中添加一個getFromCode(int code)靜態方法,如下所示:

public static MESSAGE_TYPE getFromCode(int code) {
    for(MESSAGE_TYPE mt : MESSAGE_TYPE.values())
        if(mt.code == code)
            return mt;

    throw new IllegalArgumentException();
}

然后在你的handleMessage中:

MESSAGE_TYPE messageType = MESSAGE_TYPE.getByCode(messageHeader.getInt(ExICSProtocol.TAG_MESSAGE_TYPE));


switch(messageType){
    case PROTOCOL_HANDSHAKE:
        //handle handshake...

除非你的枚舉做了一些你沒有告訴我們的內容,否則這不是一個很好用的枚舉。 對於這種特殊情況,靜態類可能更有用(和可讀):

public class MessageType {
    public static final int PROTOCOL_HANDSHAKE = 0;
    public static final int USER_CONNECTED = 1;
    ....
}

然后在你的switch語句中,你可以使用

switch( messageType ) {
    case MessageType.PROTOCOL_HANDSHAKE:
        ....
        break;

這基本上是Android在其他領域(例如ContentResolver,Database等)提倡的合同類模式。

您正在使用在運行時評估的函數。 將相同的值放在int中也不起作用,因為它也在運行時進行評估。 將值放在private final static int會起作用,因為它是在編譯時計算的,因此是一個常量表達式。

嘗試類似的東西

private final static int PROTOCOL_HANDSHAKE = 0;

並在您的switch語句中執行此操作

case PROTOCOL_HANDSHAKE:
//Do something

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM