简体   繁体   English

Java枚举(或int常量)vs c enum

[英]Java enum (or int constants) vs c enum

I'm trying to do something that would normally look like this in C: 我正试图在C中做一些通常看起来像这样的事情:

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

Approach 1 方法1

Here is what I have in Java, using enum : 以下是我在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);
    }
}

Approach 1 - Problems 方法1 - 问题

I find that I am having to repeat this pattern in various places, but was wondering: is there a better way? 我发现我不得不在不同的地方重复这种模式,但是想知道:有更好的方法吗? particularly because: 特别是因为:

  1. this seems convoluted and less elegant, and 这似乎令人费解,不那么优雅,而且
  2. it also shifts something that would be compile time to run time". 它还将编译时间改为运行时“。

One of the reasons I use this mapping, is because it looks better in switch statements, eg: 我使用此映射的原因之一是因为它在switch语句中看起来更好,例如:

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

I suppose there are also benefits of stronger type safety with enums. 我认为使用枚举更强的类型安全性也有好处。

Approach 2 I am aware I could do: 方法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;
}

but my feeling is that enum s are still better. 但我的感觉是, enum仍然更好。 Is my enum approach above the way to go? 我的enum方法是否已经超越了前进的方向? or is there another way? 还是有另一种方式?

My feeling is that in purposes only for switch statement enum is superfluous in your case, and it is better simply using final static int constants. 我的感觉是,仅用于switch语句enum在你的情况下是多余的,并且最好简单地使用final static int constants。 For instance of memory economy. 例如记忆经济。

Also, Joshua Bloch in his Effective Java recommends using enum s instead of int constants in his Item 30: Use enums instead of int constants . 此外,约书亚布洛赫在他的Effective Java建议使用enum !而非int在他的常数Item 30: Use enums instead of int constants But IMHO it is correct way of enum using for more complicated cases then just replacing c #define construction. 但恕我直言,这是用于更复杂案例的enum正确方法,然后只需替换c #define构造。

UPDATE : as author mentioned in his comment to this my answer, he is wondering is use if enum is better then int constants in general. 更新 :由于笔者在他的这个我的回答评论中提及,他想知道如果用enum是更好然后int一般常量。 In this case such question becomes duplicate (see Java: Enum vs. Int ), and my answer will: in general enum s are better, and why - look at Joshua Bloch's Item 30 , as I mentioned before. 在这种情况下,这样的问题变得重复(参见Java:Enum vs. Int ),我的回答是: 一般来说, enum更好,为什么 - 看看Joshua Bloch的Item 30 ,如前所述。

You are mixing two concepts here. 你在这里混合两个概念。 #define allows you to use the preprocessor . #define允许您使用预处理器 The compiler will just know the value you defined. 编译器只知道您定义的值。

In Java using Enums for just Port Numbers seems unreasonable, as they should be configurable imo. 在Java中使用Enums仅用于端口号似乎是不合理的,因为它们应该是可配置的imo。

I would recommend using an interface with factories (surounded by enumeration for default types, allowing 3rd party to add new interfaces [OOP]. 我建议使用带工厂的接口(默认类型的枚举包围,允许第三方添加新接口[OOP]。

Generally speaking i would not use Enumerations for constants, simply because they should be scoped within the proper class. 一般来说,我不会将Enumerations用于常量,只是因为它们应该在适当的类中作用域。

You can import constants with a static import if you want to increase readability.* 如果要提高可读性,可以使用静态导入导入常量。*

*I would consider static imports bad practice tho. *我会考虑静态导入不好的做法。

You could create a couple of classes like this: 你可以创建几个这样的类:

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

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM