关于枚举的问题

时间:2011-09-05 08:09:51

标签: java enums

如果我有一个对象

public class Genre {
    private int id;
    private int name;
}

并且id和名称已经提前确定,例如

if (id == 1)
    name = "action";
else if (id == 2)
    name = "horror";

我的问题是如何很好地创建这两种方法

Genre.getName(1); // return "action";
Genre.getId("action"); // return 1;

我想也许我可以使用枚举,比如

public enum Genre {
    ACTION(1), HORROR(2);

    private final int id;
    private final String name;

    private Genre(int id) {
        this.id = id;
        this.name = getName(id);
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public static String getName(int i) {
        switch(i) {
        case 1 : return "action";
        case 2: return "horror";
        default :
            return null;
        }
    }
}

但是这样,我不知道如何

Genre.getId("action"); // return 1;

我害怕我不正确地使用枚举。 你能给我一些建议吗?谢谢!
---
首先,我想要做的是在我的情况下,我想使用id或名称来查找名称或ID,如

int id = 1;
Genre.getName(id); // return "action"

String name = "action";
Genre.getId(name); // return 1

现在感谢所有的建议,我意识到我想要做的是

int id = 1;
Genre.getGenre(id); // return Genre that id = 1 and the name = "action"

String name = "action";
Genre.getGenre(name); // return Genre that id = 1 and the name = "action"

8 个答案:

答案 0 :(得分:3)

如果你坚持使用枚举,你可以使用现有的枚举设施。下面的解决方案假定枚举名称和序号可用于代替您的姓名和ID字段:

public enum Genre {

    // ordinal 0, name = "ACTION"
    ACTION,

    // ordinal 1, name = "HORROR"
    HORROR;
}

public static void main(String[] args) {

    int horrorOrdinal = 1;
    Genre horrorGenre = Genre.values()[horrorOrdinal];
    String horrorName = horrorGenre.name();

    String actionName = "ACTION";
    Genre actionGenre = Genre.valueOf(actionName);
    int actionOrdinal = actionGenre.ordinal();

    System.out.println(String.format("%s=%s %s=%s", horrorName, horrorOrdinal, actionName, actionOrdinal));
}

输出:

HORROR=1 ACTION=0

另一种合适的方法是使用地图进行查找,例如MichałŠrajer建议:

private static Map<Integer, String> genres = new HashMap<Integer, String>();

public static void main(String[] args) {

    initGenres();

    int horrorOrdinal = 2;
    String horrorName = genres.get(horrorOrdinal);

    String actionName = "action";
    int actionOrdinal = getGenreIdByName(actionName);

    System.out.println(String.format("%s=%s %s=%s", horrorName, horrorOrdinal, actionName, actionOrdinal));
}

private static void initGenres() {
    genres.put(1, "action");
    genres.put(2, "horror");
}

private static int getGenreIdByName(String genreName) {
    for (Entry<Integer, String> entry : genres.entrySet()) {
        if (entry.getValue().equals(genreName)) {
            return entry.getKey();
        }
    }
    throw new IllegalArgumentException("Genre not found: " + genreName);
}

输出:

horror=2 action=1

设计考虑因素:

在这个例子中,我选择对id-&gt; name使用(快速)地图查找,并编写了一个单独的方法(getGenreIdByName)来执行反向查找name-&gt; id。您可以反转它,或使用第二个映射来快速进行两次查找(代价是需要维护额外的映射)。

我选择在地图中存储ID和名称。您也可以使用Genre类本身作为地图值。这将允许您稍后轻松添加额外的字段(如“描述”)。

如果您需要用不同语言表示类型,可以使用ResourceBundles来本地化输出。在类路径根目录中创建语言文件。

在文件genres_nl.properties中:

horror=heel eng
action=actie

文件名中的_nl后缀表示语言。

然后在你的代码中,在initGenres中:

ResourceBundle genreNames = ResourceBundle.getBundle("genres", new Locale("nl");

获得流派名称时:

String horrorName = genreNames.getString(genres.get(horrorOrdinal));

请注意,如果找不到捆绑包,getString可能会抛出运行时异常MissingResourceException。为避免这种情况,请确保创建一个没有后缀的“默认”包(因此在本例中为名为“genres.properties”的文件),如果找不到所使用的Locale的包,则会自动使用该包。

答案 1 :(得分:2)

尝试valueOf(...)方法:

void String getId(String name) {
  //names are upper case, so account for that
  //handling non-existent names is an excersize for you
  valueOf(name.toUpperCase()).getId(); 
}

请注意,有更好的方法(如Thilo建议),但如果您只有字符串,则可以使用它。

编辑:另一个注意事项:

getName(int i)方法中,您可能希望返回ACTION.name()等,以便更安全地重构并使用正确的案例。

答案 2 :(得分:2)

您可以通过调用Genre.ACTION.getId();

来获取其ID

答案 3 :(得分:1)

这应该这样做:

Genre.ACTION.getId()

如果你需要在运行时这样做:

Genre.valueOf("ACTION").getId()

答案 4 :(得分:1)

ACTION(1, "action"), HORROR(2, "horror"); 

是一种简单的方法。 但如果你需要更频繁地做,我会建议你创建自己的课程并使用MAP<-"-,-"->作为micheal说。

编辑:----

正如你所说,很少会改变使用这种方式 - &gt;

    public enum Genre {
    ACTION(0, "action"), HORROR(1, "horror"), ROMANCE(2, "romance"), COMEDY(5, "comedy");
    public final int id;
    public final String name;

    private Genre(int id, String name) {
        this.id = id;
        this.name = name;
    };

    public final static int length = Genre.values().length;

    public static String[] getGenre() {
        String[] genreList = new String[length];
        int i = 0;

        for (Genre attribute : Genre.values()) {
            genreList[i++] = attribute.toString();
        }
        return genreList;
    }

    @Override
    public String toString() {
        return this.name;
    }
}

请记住将其用作Genre.HORROR.id 另请注意,根据您的要求,使用这种方式最佳。

答案 5 :(得分:0)

为什么不使用带有id和String的枚举构造函数:

public enum Genre {
    ACTION(1, "action"), HORROR(2, "horror");
}

答案 6 :(得分:0)

public enum Genre {
    ACTION(1, "action"), HORROR(2, "horror");

    private final int id;
    private final String name;

    private Genre(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

答案 7 :(得分:0)

如果您需要按名称访问特定元素,则需要这样做:

Genre.valueOf("ACTION").getId()

但是,如果您需要经常这样做,并且以更动态的方式,我建议创建常规类,并将所有数据保存在某个Map<String, Movie>容器中。