Java 枚举(或 int 常量)与 c 枚举

Java enum (or int constants) vs c enum

我正在尝试做一些在 C:

中通常看起来像这样的事情
typedef enum {
    HTTP  =80, 
    TELNET=23, 
    SMTP  =25, 
    SSH   =22, 
    GOPHER=70} TcpPort;

方法一

这是我在 Java 中的内容,使用 enum:

public static enum TcpPort{
    HTTP(80),
    TELNET(23),
    SMTP(25),
    SSH(22),
    GOPHER(70);

    private static final HashMap<Integer,TcpPort> portsByNumber;
    static{
        portsByNumber = new HashMap<Integer,TcpPort>();
        for(TcpPort port : TcpPort.values()){
            portsByNumber.put(port.getValue(),port);
        }
    }
    private final int value;
    TcpPort(int value){
        this.value = value;
    }
    public int getValue(){
        return value;
    }
    public static TcpPort getForValue(int value){
        return portsByNumber.get(value);
    }
}

方法 1 - 问题

我发现我不得不在不同的地方重复这个模式,但我想知道:有没有更好的方法?特别是因为:

  1. 这看起来很复杂而且不够优雅,
  2. 它还将编译时间转移到 运行 时间。

我使用此映射的原因之一是因为它在 switch 语句中看起来更好,例如:

switch(tcpPort){
    case HTTP:
        doHttpStuff();
        break;
    case TELNET:
        doTelnetStuff();
        break;
    ....
}

我想枚举也有更强的类型安全性的好处。

方法二 我知道我可以做到:

public static class TcpPort{
    public static final int HTTP   = 80;
    public static final int TELNET = 23;
    public static final int SMTP   = 25;
    public static final int SSH    = 22;
    public static final int GOPHER = 70;
}

但我的感觉是enum还是比较好。我的 enum 方法是否可行?或者有其他方法吗?

我的感觉是,in purposes only for switch statement enum 在你的情况下是多余的,最好只使用 final static int 常量。例如内存经济。

此外,Joshua Bloch 在他的 Effective Java 中建议在他的 Item 30: Use enums instead of int constants 中使用 enums 而不是 int 常量。但恕我直言,这是 enum 用于更复杂情况的正确方法,然后只需替换 c #define 构造。

UPDATE:正如作者在他对我的回答的评论中提到的,他想知道是否使用 enum 通常比 int 常量更好.在这种情况下,这样的问题就变得重复了(见 Java: Enum vs. Int),我的回答是: 一般来说 enum 更好,为什么 - 看看 Joshua Bloch 的 Item 30,正如我之前提到的。

您在这里混淆了两个概念。 #define 允许你使用 preprocessor。编译器只会知道您定义的值。

在 Java 中,仅对端口号使用枚举似乎不合理,因为我认为它们应该是可配置的。

我建议使用工厂接口(由默认类型的枚举包围,允许第 3 方添加新接口 [OOP]。

一般来说,我不会将枚举用于常量,只是因为它们应该在适当的 class 范围内。

如果您想提高可读性,可以使用 static import 导入常量。*

*我认为静态导入是不好的做法。

您可以像这样创建几个 类:

package com.ggl.testing;

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

public class TCPPort {

    private List<Port> ports;

    public TCPPort() {
        this.ports = new ArrayList<Port>();
        this.ports.add(new Port("HTTP", 80));
        this.ports.add(new Port("TELNET", 23));
        this.ports.add(new Port("SMTP", 25));
        this.ports.add(new Port("SSH", 22));
        this.ports.add(new Port("GOPHER", 70));
    }

    public Port getPortByName(String portName) {
        for (Port p : ports) {
            if (portName.equals(p.getPortName())) {
                return p;
            }
        }

        return null;
    }

    public Port getPortByNumber(int portNumber) {
        for (Port p : ports) {
            if (portNumber == p.getPortNumber()) {
                return p;
            }
        }

        return null;
    }

    public class Port {

        private final int portNumber;

        private final String portName;

        public Port(String portName, int portNumber) {
            this.portName = portName;
            this.portNumber = portNumber;
        }

        public int getPortNumber() {
            return portNumber;
        }

        public String getPortName() {
            return portName;
        }

    }

}