e.getMessage()和e.getLocalizedMessage()之间的区别

112

Java异常中的getMessagegetLocalizedMessage方法有什么区别?

我在进行错误处理时使用这两种方法来获取catch块抛出的消息。它们都可以从错误处理中获取消息,但它们有什么具体区别呢?

我在互联网上搜索到了Answers.com上的答案:

Java异常继承了Throwable类的getMessage和getLocalizedMessage方法(请参见相关链接)。不同之处在于,子类应该重写getLocalizedMessage方法来提供特定于语言环境的消息。
例如,假设您正在将代码从一个美国英语组织适配到一个英国英语组织。您可能想要创建自定义异常类,以覆盖getLocalizedMessage方法,以纠正拼写和语法,使用户和开发人员能够按照他们所期望的方式使用您的代码。这也可以用于实际的异常消息翻译。

问题:

  • 这是否意味着语言特定的实现? 比如,如果我在我的应用程序中使用e.getLocalizedMessage(),例如我的应用程序是用英语编写的-错误将以英语抛出,如果我将我的应用程序使用西班牙语 - 那么错误将以西班牙语抛出?

  • 需要一些清晰的解释,在何时何地可以使用这些方法。


1
是的,它意味着区域设置(语言、文化)特定的实现。官方文档有什么问题吗? - default locale
7个回答

92

正如上面所有人提到的那样--

据我理解,getMessage() 返回异常的名称。getLocalizedMessage() 返回用户本地语言(例如中文、日语等)下的异常名称。为使其有效,您调用getLocalizedMessage() 的类必须覆盖getLocalizedMessage() 方法。如果未覆盖,则调用它的超类之一的方法,该方法默认情况下只返回getMessage的结果。

此外,我想加入一些代码段来解释如何使用它。

如何使用

Java没有任何魔法,但它提供了一种简化我们生活的方法。 要有效地使用getLocalizedMessage(),我们必须覆盖默认行为。

import java.util.ResourceBundle;

public class MyLocalizedThrowable extends Throwable {

    ResourceBundle labels = ResourceBundle.getBundle("loc.exc.test.message");

    private static final long serialVersionUID = 1L;
    public MyLocalizedThrowable(String messageKey) {
        super(messageKey);
    }

    public String getLocalizedMessage() {
        return labels.getString(getMessage());
    }
}

java.util.ResourceBundle 用于实现本地化。

在这个例子中,你需要将特定语言的属性文件放置在 loc/exc/test 路径下。例如:

message_fr.properties (包含一些键和值):

key1=this is key one in France

message.properties(包含一些键和值):

key1=this is key one in English

现在,让我们假设我们的异常生成器类是这样的:

public class ExceptionGenerator {

    public void generateException() throws MyLocalizedThrowable {
        throw new MyLocalizedThrowable("key1");
    }
}

主要的类是:

public static void main(String[] args) {
    //Locale.setDefault(Locale.FRANCE);
    ExceptionGenerator eg = new ExceptionGenerator();

    try {
        eg.generateException();
    } catch (MyLocalizedThrowable e) {
        System.out.println(e.getLocalizedMessage());
    }
}

默认情况下,如果您在“英语”环境中执行,则会返回“英语”键值。如果您将本地设置为法国,则将从message_fr文件获取输出。

何时使用它

如果您的应用程序需要支持l10n/i18n,则需要使用它。但大多数应用程序不需要,因为大多数错误消息不是面向最终客户,而是面向支持工程师/开发工程师。


12
据我理解,getMessage() 返回异常的名称。这是错误的。异常的名称可以从 e.getClass().getSimpleName() 中找到。new NullPointerException().getMessage() 返回的是 "null",而不是 "NullPointerException"。 - Philip Whitehouse
2
然而,这里的陷阱在于该方法实际上并不接受区域设置,因此无法始终获取用户的区域设置。特别是,本答案中异常的实现方式只会为 GUI 应用程序正确地本地化异常。对于服务器端应用程序,JVM 的默认区域设置与用户的区域设置不同,因此最好的策略是永远不要调用 ResourceBundle.getBundle(String),而始终提供用户的实际区域设置。(例如,在 Web 应用程序中,通常会在标头中接收有关用户区域设置的信息。) - Hakanai
1
第一条语句本身就是错误的。getMessage()返回可抛出/异常的详细消息字符串。 - Kuldeep Jain
Philip和Kuldeep:友善点。你们关注的不是主要问题,而且有点苛刻。...另外,Philip:如果你想要一丝不苟,e.getClass().getSimpleName()是异常类的名称;这与异常的名称可以说是不同的。...只需将'name'读作'description'。也许有权限编辑帖子的人可以进行更改。 - steve

9

这真是令人惊讶——查看Throwable.java类的openJDK 7代码。

getLocalizedMessage的实现如下:

390     public String getLocalizedMessage() {
391         return getMessage();
392     }

getMessage 方法的实现如下:

376     public String getMessage() {
377         return detailMessage;
378     }

"And"(与)
130     private String detailMessage;

这两种方法的实现没有变化,只有文档有所不同。


23
文档明确说明:“子类可以重写此方法以生成特定于区域设置的消息。对于没有重写此方法的子类,默认实现返回与getMessage()相同的结果。” - fool4jesus

5
不是指特定语言的实现,而是指使用国际化(即i18n)机制的实现。请参见此页面,了解资源包是什么以及如何使用它们的更多细节。
要点是将任何文本放入资源文件中,您可以拥有许多这样的文件(每个区域设置/语言等一个),您的代码使用机制在正确的资源文件中查找文本(我提供的链接详细介绍了该过程)。
至于何时和何地使用此功能完全取决于您。通常,只有当您想向非技术用户呈现异常时(这些用户可能不太懂英语),才需要考虑此问题。例如,如果您只是写入日志(通常只有技术用户会阅读,因此不是常见的i18n目标),则应执行以下操作:
try {
   somethingDangerous();
} catch (Exception e) {
   log.error("got this: "+e.getMessage());
}

但是如果你打算在屏幕上显示异常消息(例如作为一个小对话框),那么你可能想要用本地语言显示消息:

try {
   somethingDangerous();
} catch (Exception e) {
   JOptionPane.showMessageDialog(frame,
    e.getLocalizedMessage(),
    "Error",  <---- also best be taken from i18n
    JOptionPane.ERROR_MESSAGE);
}

3
public String  getMessage() 

返回此可抛出对象的详细消息字符串。
public String getLocalizedMessage() 

创建此throwable的本地化描述。子类可以覆盖此方法以生成特定于语言环境的消息。对于未覆盖此方法的子类,默认实现返回与getMessage()相同的结果。

在您的情况下,e只是异常对象...

getLocalizedMessage()需要重写并提供自己的消息,即本地化消息的含义。

例如...如果出现空指针异常...

打印e将显示null。

e.getMessage() ---> NullPointerException

2
这是Throwable.java类的一些说明,也许可以帮助某些人:
/**
 * Returns the detail message string of this throwable.
 *
 * @return  the detail message string of this {@code Throwable} instance
 *          (which may be {@code null}).
 */
public String getMessage() {
    return detailMessage;
}

/**
 * Creates a localized description of this throwable.
 * Subclasses may override this method in order to produce a
 * locale-specific message.  For subclasses that do not override this
 * method, the default implementation returns the same result as
 * {@code getMessage()}.
 *
 * @return  The localized description of this throwable.
 * @since   JDK1.1
 */
public String getLocalizedMessage() {
    return getMessage();
}

-3
据我所知,getMessage返回异常的名称。getLocalizedMessage返回用户本地语言(中文、日语等)中异常的名称。为了使其工作,您调用getLocalizedMessage的类必须覆盖getLocalizedMessage方法。如果没有覆盖,则调用其中一个超类的方法,默认情况下只返回getMessage的结果。
因此,在大多数情况下,结果将是相同的,但在某些情况下,它将返回以程序运行区域的语言命名的异常名称。

这是否意味着特定于语言的实现?例如,如果我使用e.getLocalizedMessage(),例如我的应用程序是英语-错误将以英语抛出,如果我在西班牙使用我的应用程序-那么错误将以西班牙语抛出

public String 
getMessage() 

Returns the detail message string of this throwable.





public String 
getLocalizedMessage() 

创建此可抛出对象的本地化描述。子类可以重写此方法以生成特定于区域设置的消息。对于未覆盖此方法的子类,默认实现返回与getMessage()相同的结果。

在您的情况下,e只是异常对象的名称...

getLocalizedMessage() u need to override and give your own message i.e 
the meaning for localized message. 

例如...如果出现空指针异常...
通过打印e,它将显示null。
e.getMessage() ---> NullPointerException 

阅读更多...


-4
据我理解,getMessage 返回异常的名称。 getLocalizedMessage 返回用户本地语言(中文、日语等)的异常名称。
为了使其正常工作,您调用 getLocalizedMessage 的类必须重写 getLocalizedMessage 方法。
如果没有重写,将调用其超类之一的方法,默认情况下只返回 getMessage 的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接