枚举';s toString方法和Java良好实践
我想问一下Java中良好的编码实践。我想创建一些属性的枚举,并重写枚举';s toString方法和Java良好实践,java,jsf,enums,Java,Jsf,Enums,我想问一下Java中良好的编码实践。我想创建一些属性的枚举,并重写toString()以以下方式使用它(JSF 1.2用于检索本地化消息): 我的问题是关于良好实践。将所有这些方法放在enum定义中是否被认为是好的?如果没有,我想了解为什么以及如何做得更好。这里有两点需要说明: 如果默认情况(代码中返回null)是运行时错误,那么使用开关有点容易出错。我认为有两个更好的选择: 使用在枚举实例的构造函数中初始化的字段localizationKey,并在toString方法中引用此键 或者,(对于更
toString()
以以下方式使用它(JSF 1.2
用于检索本地化消息):
我的问题是关于良好实践。将所有这些方法放在
enum
定义中是否被认为是好的?如果没有,我想了解为什么以及如何做得更好。这里有两点需要说明:
开关
有点容易出错。我认为有两个更好的选择:
localizationKey
,并在toString
方法中引用此键toString
抽象化,并强制使用正确的实现覆盖每个实例。例如,见toString
要么用于真正明显的实现,要么仅用于调试。我的建议是:使用更具描述性的方法名,不要为了方便而重用toString
更新:稍微缩小Java语义:正如BalusC在下面的评论中指出的那样,此逻辑属于视图而不是模型。我将确保所有复杂逻辑只在初始化时执行一次
public enum StatisticItems {
MESSAGES("messages"),
VIEWS("views");
final String asString;
StatisticItems(String localised) {
asString = getLocalizedMsg(localised + ".title");
}
@Override
public String toString () {
return asString;
}
private static String BUNDLE_NAME = "messages";
private static final Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
private static String getLocalizedMsg(String key) {
String resourceString;
try {
resourceString = bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
if (arguments == null) {
return resourceString;
}
MessageFormat format = new MessageFormat(resourceString, locale);
return format.format(arguments);
}
}
Downvoter,为什么是downvote?让
toString()
方法复杂到当您试图打印调试消息时可能会抛出异常,这似乎是个坏主意。在将来与JSF相关的问题中,您最好不要标记[java]。没有一个回答者考虑到FacesContext
,这使得两个答案在JSF上下文中在技术上都是错误的。而且,您最好在codereview.se发布代码审阅请求,而不是在SO。或者至少从问题中消除主观性/论证性(包括“最佳实践”等词语)。要获得真正的答案,请在这里使用三个简单的关键字“jsf”、“enum”、“localization”进行搜索。我以前已经回答过这类问题。这里不需要基于每个值进行重写—只需在构造函数中私有消息名,将其存储在字段中,然后在单个实现中使用它,就会更简洁。1。你说我可以为每种情况覆盖toString是什么意思?你不是想试试(统计学家)吗?谢谢@JonSkeet。答案已更新。用户3663882,请参阅第1.2项上的链接。更优雅的做法是将本地化从模型完全移动到视图。这绝对不是模特的责任。@BalusC,我没有想到这一点,但我100%同意。在答案的底部添加了一句话。我不确定是否需要将所有复杂的逻辑放在costructor中,在这种情况下,包括在costructor中加载ResourceBundle(更不用说枚举构造函数了,因为它们是在类加载时执行的)。例如,请参阅。@aioobe-如果这看起来有点太重,那么后面会有各种机制来执行它,例如s。哦,请不要。语言环境是在这个特定的上下文中基于HTTP请求/JSF视图的,这肯定不是应用程序范围。将来,在作为答案进行之前,请亲自测试代码。@BalusC-该代码是从OP复制的。我所做的只是使其成为static final
。但我同意语言环境应该来自上下文。嗯?OP在threadlocal的基础上做得很好,但您将其设置为常量并引入了一个潜在的NPE。
public enum StatisticItems {
MESSAGES("messages"),
VIEWS("views");
final String asString;
StatisticItems(String localised) {
asString = getLocalizedMsg(localised + ".title");
}
@Override
public String toString () {
return asString;
}
private static String BUNDLE_NAME = "messages";
private static final Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
private static String getLocalizedMsg(String key) {
String resourceString;
try {
resourceString = bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
if (arguments == null) {
return resourceString;
}
MessageFormat format = new MessageFormat(resourceString, locale);
return format.format(arguments);
}
}