【问题标题】:Java enum (or int constants) vs c enumJava 枚举(或 int 常量)与 c 枚举
【发布时间】:2015-04-29 13:24:21
【问题描述】:

我正在尝试做一些在 C 语言中通常看起来像这样的事情:

typedef enum {
    HTTP  =80, 
    TELNET=23, 
    SMTP  =25, 
    SSH   =22, 
    GOPHER=70} TcpPort;

方法 1

这是我在 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;
    ....
}

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

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

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;
}

但我的感觉是enums 还是更好。我的enum 方法是否可行?还是有其他方法?

【问题讨论】:

  • 你不能比较无与伦比的东西,因为java没有任何define构造
  • 如果使用 C 编写代码,则只需使用 #define。 Java 至少有两种方法可以解决相同的问题——使用enumstatic int。在我开始使用上面的模式删除 enums 之前,我正在与社区确认没有更好的方法,并且这是正确的方法。

标签: java enums coding-style


【解决方案1】:

我的感觉是,仅用于switch 声明enum 在您的情况下是多余的,最好简单地使用final static int 常量。例如内存经济。

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

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

【讨论】:

  • 我已经澄清了这个问题——不仅仅是案例陈述,而是一般情况。
  • @xirt 在这种情况下,您还应该更改帖子的主题,而不是“enum vs define”,而是“enum vs int constants”。实际上,从这样的角度来看,您的问题变得重复或不清楚。
  • 我已经更新了标题,并在问题中添加了一些标题以澄清。所以 - 如果一般 enums 更好,实现将是方法 1 中列出的模式(即它很丑,但仍然是最好的?)跨度>
  • 我想你已经说过了,但想确认:“继续使用方法 1”:-)
【解决方案2】:

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

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

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

一般来说,我不会将枚举用于常量,仅仅是因为它们应该在适当的类中限定范围。

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

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

【讨论】:

  • 我敢肯定,OP 知道 prerpocessor 以及枚举在 java 中是如何工作的
  • 可能,我只是认为这可能很重要——考虑到 c 和 java 之间的比较。
  • 我以端口号为例。端口 80 更改为 HTTP 以外的其他内容的可能性...低到可以硬编码恕我直言。
  • 我已经用枚举替换了#define 预处理器,使它更适合苹果比较。同样的问题也适用。
【解决方案3】:

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

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;
        }

    }

}

【讨论】:

    猜你喜欢
    • 2011-07-09
    • 2011-01-14
    • 1970-01-01
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多