2011-09-05 96 views
1

如果我有一个对象约枚举问题

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" 
+0

+1代码的好解释。 – amod

回答

1

这应做到:

Genre.ACTION.getId() 

如果你需要在运行时做到这一点:

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

谢谢!但是如果我一开始不了解流派。例如,我只得到一个字符串“行动”,我怎么能把它变成Genre.Action? – cht

+0

这就是'valueOf'的作用(你应该使该字符串的名称与该字符串的名称相同,而不是一个大写和一个小写) – Thilo

+0

因此,如果我想要的实际值不是“ACTION”,而是其他语言中的“ACTION”像中国人,这种方式不推荐? – cht

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()等。

+1

您假定名称字段与枚举名称有某种关系。 –

+0

@Adriaan是的,至少从发布的源代码看起来如此,尤其是。因为枚举版本没有构造函数的名称参数。 – Thomas

2

您可以通过调用Genre.ACTION来获得其ID。的getId();

0

你为什么不使用枚举构造与ID和字符串:

public enum Genre { 
    ACTION(1, "action"), HORROR(2, "horror"); 
} 
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; 
    } 
} 
0

如果您需要通过它的名称来访问特定的元素,你需要做的是这样:

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

但是,如果你需要经常这样做,在更动态的方式,我建议建立普通班,并保持所有数据在一些Map<String, Movie>容器。

+0

对不起,我的JAVA和英语。 “将所有数据保存在Map ”中意味着什么? – cht

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

是一个简单的方法来做到这一点。 但如果你需要更经常地做,我会建议你创建你自己的类,并使用MAP<-"-,-"->作为迈克尔说。

编辑:----

至于你说的很少能改变用这种方式 - >

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 还指出,使用这种方式是最好的,因为根据您的要求。

+1

谢谢!你的意思是,如果我需要改变流派,就像添加或删除流派一样。那么,我创造了对象为行动和恐怖更好? – cht

+0

是的,因为枚举应该被引用为常量。这些值很少会改变。为了经常改变价值,你为什么不喜欢上课?其全部符合您的要求。最近我也遇到了同样的问题,我的名字和id是不变的,只有少数名字像你一样有HORROR,ACTION我使用了类,但后来我发现了一个更好的方法,用enum做。如果他们很少会改变为枚举。告诉我是否需要任何代码会编辑我的答案。 – amod

+0

我认为在我的情况下,它很少改变。但我仍然想知道如果经常改变它,该怎么做。如果我经常改变它,我怎么写呢?因为如果我创建一个对象操作,并给它的ID和名称。我如何才能使用String“action”来获取Object Action?谢谢! – cht

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 

另一种合适的方法是使用地图的查询,像米哈尔Š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->的名字并写了一个单独的方法(getGenreIdByName)做反向查找名称 - > ID。你可以扭转,或者使用第二个地图,使这两个查询快(在需要保持一个额外的地图的费用)。

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

如果你需要,你代表在不同的语言风格,你可以用把ResourceBundle本地化输出。在你的类路径根目录下创建一个语言文件。

在文件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的包的情况下自动使用。

+0

谢谢!这真的很有用,我需要一些时间来消费! – cht

+0

'如果你坚持使用枚举来实现这个......' - 如果流派的数量是固定的,那么我更喜欢enum版本,即在运行时可能不会改变。 – Thomas

+0

@Thomas我不认为这是主要标准。如果你需要引用很多不同的流派(比如你的代码中有Genre.ACTION等),我会使用枚举。但是,如果这被用于Web应用程序中,并且ID /名称被动态地传递到/从前端/持久层,那么我认为像地图这样的缓存查找更有意义。最重要的是,像电影类型这样的数据在我的经验中几乎没有变化。作为一种预防措施,我会将其建模为一个持久实体,以避免为每次更改流派重新部署我的应用程序。 –