Java中定义字符串常量的编程实践

10

我认为,在Java中定义字符串常量的目的是当在多个地方使用相同的字符串时应该定义一个字符串常量。这有助于减少拼写错误、减少将来更改字符串所需的工作量等。

但是对于只在单个地方使用的字符串,我们是否应该在这种情况下声明字符串常量呢?

例如,记录某些计数器(随机示例)。

CounterLogger.addCounter("Method.Requested" , 1)
  • 声明常量与使用原始字符串相比有什么优势?
  • 编译器是否进行任何优化?

8
不行,不能这样做。 - Robert Harvey
JVM 会将字符串字面量池中使用的所有字符串字面量组合在一起,无论这些字符串字面量出现在多少个类或 JAR 文件中。 - Peter Lawrey
不行,也不行。除了国际化之外。 - Scary Wombat
如果您将字符串定义为常量(可能在单独的类中或将它们存储在特殊文件中),那么查找和编辑它们会更加容易。有时候非常容易。 - athabaska
虽然不是主题,但我认为这个链接值得注意:https://dev59.com/FWw15IYBdhLWcg3wWqf-。 - Siva Tumma
4个回答

4

声明常量可以提高您的代码质量,因为它们可以更具描述性。在您的示例中

CounterLogger.addCounter("Method.Requested" , 1)

方法参数"Method.Requested"相当自描述,但1并不是这样。将其定义为一个常量将使示例更易读。
CounterLogger.addCounter("Method.Requested" , INITIAL_VALUE)

2
我认为,字符串可以用两种方式之一:
  • 作为属性/键/枚举——换句话说,作为应用程序的另一个对象/状态的内部表示,其中一个代码组件编写它们,另一个读取它们。
  • 在 UI 中——用于 GUI/console/logging 显示目的。
  • 我认为很容易看出,在这两种情况下都很重要避免硬编码。
    第一种类型的字符串必须(如果可能)存储为常量,并公开给可能用于输入/输出的任何程序组件。
    显示字符串(例如在 Logger 案例中)是您将来可能更改的字符串。将它们全部存储为专用于常量的类中的 static final 字段可以使以后的修改更加容易,并帮助避免类似消息的重复。
    关于优化问题——正如其他人已经回答的那样,我相信没有显著的区别。

    1
    在我的看法中,在你的情况下是可以的。如果你不能看到将其声明为常量的任何优点,那就不要这样做。支持这一观点,可以看一下Spring JdbcTemplate(我毫不怀疑Spring代码是一个好例子),它充满了像这样的字符串字面值。
    Assert.notNull(psc, "PreparedStatementCreator must not be null");
    Assert.notNull(action, "Callback object must not be null");
    throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
    

    但只有两个常量。
    private static final String RETURN_RESULT_SET_PREFIX = "#result-set-";
    private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";
    

    Iterestingly, this line

    Assert.notNull(sql, "SQL must not be null");
    

    在代码中重复5次,尽管作者拒绝将其作为常量。


    1
    假设你想为包含那行代码的方法编写单元测试。该单元测试将需要访问该字符串值。如果您不使用常量,则会重复使用该字符串,并且如果将来必须更改它,则必须在两个位置更改它。因此最好使用常量,即使编译器不会执行任何有用的优化。

    我不同意。单元测试只应该知道要使用哪个字符串常量,如果它是被测试方法的参数。在这种情况下,单元测试需要明确指定要使用的字符串值。 如果有人去实现类并更改常量,则测试应该会失败,并迫使开发人员审查它们并更新它们以确认此类的接口正在发生变化。 - Iker Jimenez

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