在 Java 中定义错误代码/字符串的最佳方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/446663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:44:13  来源:igfitidea点击:

Best way to define error codes/strings in Java?

javaenums

提问by William Brendel

I am writing a web service in Java, and I am trying to figure out the best way to define error codes and their associated error strings. I need to have a numerical error code and an error string grouped together. Both the error code and error string will be sent to the client accessing the web service. For example, when a SQLException occurs, I might want to do the following:

我正在用 Java 编写一个 Web 服务,我试图找出定义错误代码及其相关错误字符串的最佳方法。我需要将数字错误代码和错误字符串组合在一起。错误代码和错误字符串都将发送到访问 Web 服务的客户端。例如,当发生 SQLException 时,我可能想要执行以下操作:

// Example: errorCode = 1, 
//          errorString = "There was a problem accessing the database."
throw new SomeWebServiceException(errorCode, errorString);

The client program might be shown the message:

客户端程序可能会显示以下消息:

"Error #1 has occured: There was a problem accessing the database."

“发生错误 #1:访问数据库时出现问题。”

My first thought was to used an Enumof the error codes and override the toStringmethods to return the error strings. Here is what I came up with:

我的第一个想法是使用Enum错误代码并覆盖toString方法以返回错误字符串。这是我想出的:

public enum Errors {
  DATABASE {
    @Override
    public String toString() {
      return "A database error has occured.";
    }
  },

  DUPLICATE_USER {
    @Override
    public String toString() {
      return "This user already exists.";
    }
  },

  // more errors follow
}

My question is:Is there a better way to do this? I would prefer an solution in code, rather than reading from an external file. I am using Javadoc for this project, and being able to document the error codes in-line and have them automatically update in the documentation would be helpful.

我的问题是:有没有更好的方法来做到这一点?我更喜欢代码中的解决方案,而不是从外部文件中读取。我在这个项目中使用 Javadoc,能够在线记录错误代码并让它们在文档中自动更新会很有帮助。

采纳答案by Jon Skeet

Well there's certainly a better implementation of the enum solution (which is generally quite nice):

好吧,枚举解决方案肯定有更好的实现(这通常非常好):

public enum Error {
  DATABASE(0, "A database error has occured."),
  DUPLICATE_USER(1, "This user already exists.");

  private final int code;
  private final String description;

  private Error(int code, String description) {
    this.code = code;
    this.description = description;
  }

  public String getDescription() {
     return description;
  }

  public int getCode() {
     return code;
  }

  @Override
  public String toString() {
    return code + ": " + description;
  }
}

You may want to override toString() to just return the description instead - not sure. Anyway, the main point is that you don't need to override separately for each error code. Also note that I've explicitly specified the code instead of using the ordinal value - this makes it easier to change the order and add/remove errors later.

您可能希望覆盖 toString() 以仅返回描述 - 不确定。无论如何,重点是您不需要为每个错误代码单独覆盖。另请注意,我已经明确指定了代码而不是使用序号值 - 这使得以后更改顺序和添加/删除错误变得更加容易。

Don't forget that this isn't internationalised at all - but unless your web service client sends you a locale description, you can't easily internationalise it yourself anyway. At least they'll have the error code to use for i18n at the client side...

不要忘记这根本没有国际化 - 但是除非您的 Web 服务客户端向您发送区域设置描述,否则您自己无法轻松地将其国际化。至少他们会有在客户端用于 i18n 的错误代码......

回答by Cowan

Overloading toString() seems a bit icky -- that seems a bit of a stretch of toString()'s normal use.

重载 toString() 似乎有点棘手——这似乎有点像 toString() 的正常使用。

What about:

关于什么:

public enum Errors {
  DATABASE(1, "A database error has occured."),
  DUPLICATE_USER(5007, "This user already exists.");
  //... add more cases here ...

  private final int id;
  private final String message;

  Errors(int id, String message) {
     this.id = id;
     this.message = message;
  }

  public int getId() { return id; }
  public String getMessage() { return message; }
}

seems a lot cleaner to me... and less verbose.

对我来说似乎更清晰......而且不那么冗长。

回答by Romain Linsolas

As far as I am concerned, I prefer to externalize the error messages in a properties files. This will be really helpful in case of internationalization of your application (one properties file per language). It is also easier to modify an error message, and it won't need any re-compilation of the Java sources.

就我而言,我更喜欢在属性文件中外部化错误消息。这在您的应用程序国际化的情况下非常有用(每种语言一个属性文件)。修改错误消息也更容易,并且不需要重新编译 Java 源代码。

On my projects, generally I have an interface that contains errors codes (String or integer, it doesn't care much), which contains the key in the properties files for this error:

在我的项目中,通常我有一个包含错误代码(字符串或整数,无关紧要)的接口,其中包含此错误的属性文件中的键:

public interface ErrorCodes {
    String DATABASE_ERROR = "DATABASE_ERROR";
    String DUPLICATE_USER = "DUPLICATE_USER";
    ...
}

in the properties file:

在属性文件中:

DATABASE_ERROR=An error occurred in the database.
DUPLICATE_USER=The user already exists.
...

Another problem with your solution is the maintenability: you have only 2 errors, and already 12 lines of code. So imagine your Enumeration file when you will have hundreds of errors to manage!

您的解决方案的另一个问题是可维护性:您只有 2 个错误,并且已经有 12 行代码。所以想象一下你的枚举文件,当你有数百个错误需要管理时!

回答by blabla999

I (and the rest of our team in my company) prefer to raise exceptions instead of returning error codes. Error codes have to be checked everywhere, passed around, and tend to make the code unreadable when the amount of code becomes bigger.

我(以及我公司的其他团队成员)更喜欢引发异常而不是返回错误代码。错误代码必须到处检查,传递,并且当代码量变大时往往使代码不可读。

The error class would then define the message.

然后错误类将定义消息。

PS: and actually also care for internationalization !
PPS: you could also redefine the raise-method and add logging, filtering etc. if required (at leastin environments, where the Exception classes and friends are extendable/changeable)

PS:其实也很关心国际化!
PPS:如果需要,您还可以重新定义 raise-method 并添加日志记录、过滤等(至少在 Exception 类和朋友是可扩展/可更改的环境中)

回答by duffymo

I'd recommend that you take a look at java.util.ResourceBundle. You should care about I18N, but it's worth it even if you don't. Externalizing the messages is a very good idea. I've found that it was useful to be able to give a spreadsheet to business folks that allowed them to put in the exact language they wanted to see. We wrote an Ant task to generate the .properties files at compile time. It makes I18N trivial.

我建议您查看 java.util.ResourceBundle。你应该关心 I18N,但即使你不关心也是值得的。将消息外部化是一个非常好的主意。我发现能够向业务人员提供电子表格,使他们能够输入他们想要看到的确切语言,这很有用。我们编写了一个 Ant 任务来在编译时生成 .properties 文件。它使 I18N 变得微不足道。

If you're also using Spring, so much the better. Their MessageSource class is useful for these sorts of things.

如果您也使用 Spring,那就更好了。他们的 MessageSource 类对这些事情很有用。

回答by Scott Stanchfield

At my last job I went a little deeper in the enum version:

在我的上一份工作中,我对枚举版本进行了更深入的研究:

public enum Messages {
    @Error
    @Text("You can''t put a {0} in a {1}")
    XYZ00001_CONTAINMENT_NOT_ALLOWED,
    ...
}

@Error, @Info, @Warning are retained in the class file and are available at runtime. (We had a couple of other annotations to help describe message delivery as well)

@Error、@Info、@Warning 保留在类文件中并在运行时可用。(我们还有一些其他注释来帮助描述消息传递)

@Text is a compile-time annotation.

@Text 是一个编译时注释。

I wrote an annotation processor for this that did the following:

我为此编写了一个注释处理器,它执行以下操作:

  • Verify that there are no duplicate message numbers (the part before the first underscore)
  • Syntax-check the message text
  • Generate a messages.properties file that contains the text, keyed by the enum value.
  • 验证没有重复的消息号(第一个下划线之前的部分)
  • 语法检查消息文本
  • 生成一个包含文本的 messages.properties 文件,以枚举值作为键。

I wrote a few utility routines that helped log errors, wrap them as exceptions (if desired) and so forth.

我编写了一些实用程序来帮助记录错误,将它们包装为异常(如果需要)等等。

I'm trying to get them to let me open-source it... -- Scott

我正试图让他们让我开源它... -- Scott

回答by pprzemek

A little late but, I was just looking for a pretty solution for myself. If you have different kind of message error you can add simple, custom message factory so that you can specify more details and format that you'd like later.

有点晚了,但是,我只是在为自己寻找一个很好的解决方案。如果您有不同类型的消息错误,您可以添加简单的自定义消息工厂,以便您可以指定更多详细信息和稍后需要的格式。

public enum Error {
    DATABASE(0, "A database error has occured. "), 
    DUPLICATE_USER(1, "User already exists. ");
    ....
    private String description = "";
    public Error changeDescription(String description) {
        this.description = description;
        return this;
    }
    ....
}

Error genericError = Error.DATABASE;
Error specific = Error.DUPLICATE_USER.changeDescription("(Call Admin)");

EDIT: ok, using enum here is a little dangerous since you alter particular enum permanently. I guess better would be to change to class and use static fields, but than you cannot use '==' anymore. So I guess it's a good example what not to do, (or do it only during initialization) :)

编辑:好的,在这里使用 enum 有点危险,因为您永久更改了特定的 enum。我想更好的是更改为类并使用静态字段,但您不能再使用 '==' 了。所以我想这是一个很好的例子,不要做什么,(或者只在初始化期间做):)

回答by Jimmy

enum for error code/message definition is still a nice solution though it has a i18n concerns. Actually we may have two situations: the code/message is displayed to the end user or to the system integrator. For the later case, I18N is not necessary. I think the web services is most likely the later case.

错误代码/消息定义的枚举仍然是一个不错的解决方案,尽管它有 i18n 问题。实际上我们可能有两种情况:代码/消息显示给最终用户或系统集成商。对于后一种情况,I18N 不是必需的。我认为 Web 服务很可能是后者。

回答by telcopro

Just to keep flogging this particular dead horse- we've had good use of numeric error codeswhen errors are shown to end-customers, since they frequently forget or misread the actual error message but may sometimes retain and report a numeric value that can give you a clue to what actually happened.

只是为了继续鞭打这个特定的死马——当错误显示给最终客户时,我们很好地使用了数字错误代码,因为他们经常忘记或误读实际的错误消息,但有时可能会保留并报告一个数字值,可以给出你对实际发生的事情有一个线索。

回答by Awan Biru

Using interfaceas message constant is generally a bad idea. It will leak into client program permanently as part of exported API. Who knows, that later client programmers might parse that error messages(public) as part of their program.

使用interface的消息常数一般是一个坏主意。它将作为导出 API 的一部分永久泄漏到客户端程序中。谁知道,后来的客户端程序员可能会将该错误消息(公共)解析为他们程序的一部分。

You will be locked forever to support this, as changes in string format will/may break client program.

您将永远被锁定以支持这一点,因为字符串格式的更改将/可能会破坏客户端程序。