Enum 的 toString 方法和 Java 良好实践
Enum's toString method and Java good practice
我想询问 Java 中的良好编码习惯。我想创建一些属性的枚举并覆盖 toString()
以按以下方式使用它(JSF 1.2
用于检索本地化消息):
package ua.com.winforce.casino.email.util;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
public enum StatisticItems {
MESSAGES,
VIEWS;
private static String BUNDLE_NAME = "messages";
public String toString(){
switch (this) {
case MESSAGES:
return getLocalizedMsg("messages.title");
case VIEWS:
return getLocalizedMsg("views.title");
default:
return null;
}
}
private static String getLocalizedMsg(String key, Object... arguments) {
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
String resourceString;
try {
ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
resourceString = bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
if (arguments == null) {
return resourceString;
}
MessageFormat format = new MessageFormat(resourceString, locale);
return format.format(arguments);
}
}
我的问题是关于良好做法的。将所有这些方法放在 enum
定义中是否被认为是好的?如果没有,我想了解原因,当然还有如何做得更好。
这里有两点需要说明:
如果默认情况(在您的代码中返回 null)是运行时错误,那么使用 switch
很容易出错。我认为有两个更好的选择:
- 使用字段
localizationKey
,在枚举实例的构造函数中初始化,并在toString
方法中引用此键
- 或者,(对于更复杂的情况)使
toString
抽象并强制每个实例以适当的实现覆盖。例如,参见 this question。
许多人认为 toString
要么用于真正明显的实现,要么仅用于调试。 (详见 this question。)我的建议:想出一个更具描述性的方法名称,不要为了方便而重复使用 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);
}
}
我想询问 Java 中的良好编码习惯。我想创建一些属性的枚举并覆盖 toString()
以按以下方式使用它(JSF 1.2
用于检索本地化消息):
package ua.com.winforce.casino.email.util;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
public enum StatisticItems {
MESSAGES,
VIEWS;
private static String BUNDLE_NAME = "messages";
public String toString(){
switch (this) {
case MESSAGES:
return getLocalizedMsg("messages.title");
case VIEWS:
return getLocalizedMsg("views.title");
default:
return null;
}
}
private static String getLocalizedMsg(String key, Object... arguments) {
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
String resourceString;
try {
ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
resourceString = bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
if (arguments == null) {
return resourceString;
}
MessageFormat format = new MessageFormat(resourceString, locale);
return format.format(arguments);
}
}
我的问题是关于良好做法的。将所有这些方法放在 enum
定义中是否被认为是好的?如果没有,我想了解原因,当然还有如何做得更好。
这里有两点需要说明:
如果默认情况(在您的代码中返回 null)是运行时错误,那么使用
switch
很容易出错。我认为有两个更好的选择:- 使用字段
localizationKey
,在枚举实例的构造函数中初始化,并在toString
方法中引用此键 - 或者,(对于更复杂的情况)使
toString
抽象并强制每个实例以适当的实现覆盖。例如,参见 this question。
- 使用字段
许多人认为
toString
要么用于真正明显的实现,要么仅用于调试。 (详见 this question。)我的建议:想出一个更具描述性的方法名称,不要为了方便而重复使用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);
}
}