提取大量字符串字面值是一个好主意吗?

3
在我处理的一个旧代码库中,有大量字符串字面量。其中许多是重复的。例如,字符串“userID”在500个地方使用。可能有一千个这样的字面量被重复使用。IntelliJ Idea静态代码分析建议我将它们提取为常量。如果IDE自动为我执行此重构,而我不需要输入任何代码,那么我应该这样做吗?
总的来说,将许多这样的重复字符串字面量提取为常量是一个好主意吗?这显然会避免重复,并提供单一的访问点、声明等。
然而,某些字面量在访问时才出现。如果我将所有字面量都声明为常量(static final),那么所有这些常量都将一起加载。在这种情况下,将所有这些字面量声明为常量是一个好主意吗?您能提供一些垃圾收集、内存空间预防措施的指针吗?在这种情况下使用的最佳实践是什么?

一些注释:我知道字符串字面量是被池化的。因此,在最坏的情况下,我认为我不会节省任何内存。另外,似乎jdk 7会将这些字符串放在堆中而不是永久代中。我看到了像我这样的几个 问题 类似的问题,但感觉不同。所以在这里发布。

谢谢


5
可能吧。这是我的看法(暗示一下),但至少可以减少错误的数量,特别是如果你需要使用某个特定的字符串。同时,这也为你提供了机会来为这个字符串添加上下文含义。 - Makoto
1个回答

6
  1. 所有字符串字面量都会自动进行 内部化(interned)。从JDK7开始,当定义字符串字面量的类(实际上是加载该类的类加载器)被垃圾回收时(前提是没有其他类引用该字符串字面量),它们也将被垃圾回收(尽管这种情况很少发生...)。将它们定义为staticfinal并放入一个公共类中确实无法节省内存,但从设计角度来说很有用,因为它将提供单一访问点。

  2. 相同的字符串字面量在JVM中的所有类之间共享。因此,不会创建新的字符串对象。将字符串字面量放到一个类中,并从那个地方访问它们,使得你的代码更有结构性/可读性。

我的建议是,除非它能带来很大的差异,否则不要调整传统代码。权衡利弊由你选择。:P


1
同意“不要动老代码”的评论。 - Scary Wombat
3
确切的说,@Atul 将字符串声明为常量的真正原因是为了减少由于拼写错误而导致的编码错误的机会 - 这样做基本上让编译器强制执行你在应该使用相同字符串的所有位置使用的字符串;同时还可以轻松地在一个地方更改字符串并为具有更多语义含义的字符串指定名称(还可以为具有相同值但不同用途的字符串提供上下文)。由于内部化,内存使用等方面没有(或很少)差别。如果旧代码可以正常工作,则没有理由进行此类更改。 - Jason C
1
同意遗留代码部分。但是,如果IDE可以自动重构提取常量,那么这仍然是一个坏主意吗? - Atul
4
很可能如此。现在进行这种更改,并且做得正确,可能比简单的查找和替换要繁琐和复杂得多。例如,您需要验证每个“userId”的出现实际上意味着相同的事情。如果其中一个是数据库列名,另一个是配置文件中无关但巧合相同的键,您可能会在语义不同的情况下意外将它们组合成相同的常量,从而使事情变得更糟。您必须分析所有这些内容。 - Jason C
1
@Atul - 补充Jason的评论,可能会有多个与之无关的“userid”字符串。也就是说,明天客户可能会要求您将其更改为“username”,那么实际上搜索和替换正确的userid字符串以使用用户名将会成为一个问题... - TheLostMind
显示剩余2条评论

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