7

我在 C++ 中经常使用这个成语:

/*return type*/ foo(/*parameters*/){
    static const char* bar = "Bar";
    /*some code here*/
}

在内部,这被添加到字符串文字表中。这个 Java 代码是否做类似的事情:

/*return type*/ foo(/*parameters*/){
    final String bar = "Bar";
    /*some code here*/
}

还是我在这里无意中引入了低效率?

4

4 回答 4

5

字符串在 Java 中是不可变的。这意味着您不必提示让 JVM 知道它不会改变和优化它。

字符串文字被保留以避免冗余,这意味着它们已经“添加到字符串文字表中”。final不需要在这里使用。

于 2013-10-23T15:10:57.447 回答
1

我认为您的解决方案是正确的,它们与 Java 可以表达的一样接近。

正如其他答案所提到的,字符串是不可变的,并且 final 不会增加任何性能增强,但是我觉得 final 在语义上是有用的。很像 C++ 中的 'const';'final' 确保无法更改该值,并且尝试这样做会导致编译器错误 - 在我看来,这在您的情况下是一种可取的行为。

此外(就像 c++ const 的情况一样)它可能会导致一些可能的优化,否则这些优化将不会被考虑。

于 2013-10-23T15:26:15.817 回答
0

String.intern()您可以通过如下调用指定将字符串添加到文字池(在 Java 中称为实习) :

final String bar = myString.intern();

它与文字池的概念基本相同,对给定的字符串使用相同的对象。请注意,字符串文字是自动实习的。它还允许您通过引用比较实习字符串,因此它可能更有效。但是,您必须始终比较通过返回的字符串intern()。因此

a.equals(b);

可以替换为

a.intern() == b.intern();

请注意,您实际上并不希望完全按照描述进行上述操作。理想情况下,您可以保留实习字符串并重复使用它们。但是,实习字符串有一些陷阱。它们不是垃圾收集的,而且方法本身有点贵。

于 2013-10-23T15:13:09.813 回答
0

Java 方法中的final关键字并不像您认为的那样做。

在这种特殊情况下,final使变量不可修改。而已。内容本身确实会添加到字符串常量的全局表中,但指向它的指针(请原谅术语)在技术上每次都设置。

final关键字主要用于方法中,使变量可用于您在它之后创建的任何匿名类。这是 Java 对他们喜欢考虑的“关闭”的支持。它也恰好是您可以从内部匿名类中访问外部变量的唯一方法。

final String bar = "Bar";
final Set<String> allTheBars = new HashSet<>() {{
    add(bar);
}};
于 2013-10-23T15:13:26.247 回答