【问题标题】:Why does Java class library still use String constants in place of enum为什么Java类库仍然使用String常量代替枚举
【发布时间】:2014-09-26 10:12:36
【问题描述】:

我正在为我正在构建的工具使用一些 Java 类,例如 javax.Mail.SessionMessageDigest

我注意到为它们分配属性很困难,因为它们为此使用了String 常量。

例如,对于Session 对象,您必须在Property 实例中分配String 键值对,然后使用该实例创建Session。因此,如果您希望会话记录调试消息,请在 Property 实例中分配 "smtp.mail.debug""true"。同样,如果您希望您的MessageDigest 使用SHA,请将MessageDigest 实例创建为MessageDigest.getInstance("SHA")

如果说我想使用MD5 / RC4 等实现MessageDigest,或者向我的Session 对象添加另一个属性,我还没有弄清楚要做什么以及从哪里获取信息。

如果这些各自的类公开公共枚举来分配属性,那不是更好吗?

至少会为程序员节省大量搜索时间。

【问题讨论】:

  • “如果这些各自的类公开公共枚举来分配属性,那不是更好吗?”不!
  • 完全同意@Raymond。我认为它只使用 String 作为常量,因为 [1] 与在 Enum 存在之前开发的 std 库向后兼容 [2] 缺乏枚举使用强制和 [3] 如果这些参数可以,则使用字符串是可以接受的唯一原因t 在编译时被发现。当您开始使用用 | 屏蔽的数字 AWT 常量时,情况会更糟。
  • @Unihedron : 除非你用推理来支持它,否则不要征求意见。
  • 有三个原因:向后兼容、向后兼容和向后兼容。

标签: java string session enums constants


【解决方案1】:

我可以看到两个主要原因:

向后兼容性

enums 在 Java 1.5 中引入之前,您提供的两个示例已经是 API 的一部分。这样的案例还有很多。

可扩展性

MessageDigest 为例。 javadoc 指定:

Java 平台的每个实现都需要支持 遵循标准 MessageDigest 算法:

• MD5
• SHA-1
• SHA-256

这让其他java.security.Provider 库为其他算法提供MessageDigest 实现,而不是API 最低要求的算法。在 API 级别的限制性 enum 中仅列出默认值会限制可扩展性。

在邮件会话属性的情况下,允许其他 javax.mail.Provider 实现支持其他/自定义属性也是如此。

【讨论】:

  • 这些理由都​​不是令人满意的。同样的方式String.getBytes("UTF-8") 可以接受String.getBytes(StandardCharsets.UTF_8),并且您不需要处理可能的UnsupportedEncodingException,可以(应该!)为MessageDigest.getInstance("MD5") 提供类似的映射。必须对编译时已知的事物进行运行时检查总是错误的。好的库可以帮助您避免这种情况。
  • @swalog 是否可以或应该提供具有相应方法的附加映射?当然可以,但是由于上述原因,这不会使基于字符串的方法的需求无效。
  • 同意。我应该很清楚你提供的理由满足了这个问题。我的批评是针对 api。我想指出,没有理由不使用常量来避免运行时字符串查找 api 所需的实现。我们本可以拥有向后兼容性可扩展性。
【解决方案2】:

这可能是因为 Java 的主要重点是提供与以前版本的向后兼容性。

enum 是在 Java 1.5 中引入的,因此针对 1.4 或更早版本编写的任何 API 都不会提供对此功能的支持。这在 JDK 中的许多 API 中很常见

您还需要记住,enum 是不可扩展的,这意味着如果您想在消息摘要中引入新算法,例如,您将被卡住......您将无法做到它。

邮件 API 也是如此,邮件 API 为截然不同的概念提供支持,并非所有概念都具有相同系列的属性,并且不可能设计出能够支持两者之间所有各种属性的单个枚举现在或将来存在的不同实现,enum 只是为了这项工作不灵活。

【讨论】:

  • 我已经读到了。但他们本可以扩展他们的 API 以允许使用枚举来分配属性,对吧?
  • @Raymond232 这不是这些 API 的重点。这些 API 旨在提供一个共同的正面,您可以通过它与interfaces 进行交互,在某些情况下。那些interfaces 仍将被限制为能够提供对他们所知道的内容的访问,而不是未来可能出现的内容......enum,在这种情况下是限制性的......
【解决方案3】:

认为原因只是向后兼容会很简单。

对于JavaMail,因为它有太多与不同连接器相关的不同设置,您只需要其中的一部分来设置与支持协议之一的连接。每个连接器都在单独的类中实现,我认为,没有理由让例如 POP3 连接器知道 IMAP 连接器的设置。

MessageDigest 的原因是支持非标准加密算法,JDK 没有打包,而是由 3rd 方 JCE 适配器提供。 例如它将如何查找 CryptoPro JCE 提供的 GOST 算法:

  MessageDigest digest = MessageDigest.getInstance("GOST3411"); 

【讨论】:

  • 我同意你的两个观点,但我正在寻找一个更通用的答案(就字符串常量的一般使用而言)。无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-02-09
  • 2014-08-22
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 2019-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多