2015-02-24 30 views
2

我想请教一下在Java中良好的编码习惯。我想创造一些属性的enumeratoin并覆盖toString()下面的方式来使用它(JSF 1.2是为了用于检索本地化消息):枚举的toString方法和Java的良好做法

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定义中是否被认为是好的?如果没有,我想了解为什么,当然如何做得更好。

+0

Downvoter,为什么downvote? – user3663882 2015-02-24 10:42:37

+0

似乎是一个糟糕的主意,因为有一个'toString()'方法足够复杂,以至于当您试图打印调试消息时它可能会引发异常。 – khelwood 2015-02-24 10:45:10

+4

在未来的JSF相关问题中,最好不要标记[java]。没有一个回答者考虑了'FacesContext',在JSF上下文中这两个回答在技术上都是错误的。而且,您最好在codereview.se上发布代码审查请求,而不是在SO上。或者至少从问题中消除主观性/论证性(包括像“最佳实践”这样的词)。对于真正的答案,请使用三个简单的关键字“jsf”,“enum”“localization”进行搜索。我以前回答过这种问题。 – BalusC 2015-02-24 11:18:37

回答

2

有两点需要在此进行:

  1. 如果默认情况下(在返回代码为null)是一个运行时错误,然后用switch是一种容易出错的。还有,我认为较好的两个备选方案:

    1. 使用领域localizationKey,在枚举实例的构造函数初始化,并参考这个按键toString方法
    2. 或者,(对于更复杂的情况下),使toString摘要并强制每个实例通过适当的实现进行覆盖。例如,请参阅this question
  2. 很多人认为toString是用于非常明显的实现,否则只用于调试。 (详细请参阅this question)我的建议:提出一个更具描述性的方法名称,为方便起见,不要重复使用toString

更新:从Java语义缩放了一点:该逻辑属于视图,而不是模型中,如在下面的评论所指出BalusC。

+0

这里不需要覆盖每个值的基础 - 只需要在构造函数中隐藏消息名称,将其存储在一个字段中,然后在单个实现中使用它,将会更清晰。 – 2015-02-24 10:44:21

+0

1.你是什么意思,我可以重写toString为每个案件?你不是指toString(StatisticItems),是吗? – user3663882 2015-02-24 10:45:07

+0

谢谢@JonSkeet。答案已更新。 user3663882,请参阅项目1.2的链接。 – aioobe 2015-02-24 10:48:33

0

我将确保所有复杂的逻辑只在INITIALISE时间做一次。

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); 
    } 
} 
+0

我不确定在这种情况下放置所有复杂的逻辑是可取的,包括在costructors中加载ResourceBundles(更不用说枚举构造函数,考虑到它们是在类加载时执行的)。请参见[在构造函数中做了很多坏事](http://stackoverflow.com/questions/7048515/is-doing-a-lot-in-constructors-bad)。 – aioobe 2015-02-24 10:58:44

+0

@aioobe - 如果这看起来有点过重,那么后面会有各种机制,例如[Multiton](http://stackoverflow.com/a/18149547/823393)。 – OldCurmudgeon 2015-02-24 11:02:43

+0

哦,请不要。区域设置在这个特定的上下文中,基于HTTP请求/ JSF视图,这绝对不是应用程序范围的。未来,请在作为答案离开之前亲自测试代码。 – BalusC 2015-02-24 11:22:44