我经常在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*/
}
或者我在这里无意中引入了低效率?
答案 0 :(得分:5)
字符串在Java中是不可变的。这意味着您不必提供让JVM知道它不会改变和优化它的提示。
字符串文字被实习以避免冗余,这意味着它们已经“添加到字符串文字表中”。在这里使用final
是没有必要的。
答案 1 :(得分:1)
我认为您的解决方案是正确的,它们几乎与Java可以表达的相同。
正如其他答案所提到的,字符串是不可变的,而最终字符串并没有添加任何性能增强,但我觉得最终在语义上很有用。很像c ++中的'const'; 'final'确保无法更改该值,并且尝试这样做会导致编译器错误 - 在我看来,这是您理想的行为。
此外(与c ++ const的情况一样)它可能会导致一些可能的优化,否则将不予考虑。
答案 2 :(得分:0)
您可以通过调用String.intern()
指定要添加到文字池的字符串(在Java中称为实习),如下所示:
final String bar = myString.intern();
它与文字池基本相同,对给定字符串使用相同的对象。请注意,字符串文字会自动实现。它还允许您通过引用比较实习字符串,因此可能更有效。但是,您必须始终比较通过intern()
返回的字符串。因此
a.equals(b);
可以替换为
a.intern() == b.intern();
请注意,您实际上并不完全如上所述。理想情况下,您可以保留固定的字符串并重复使用它们。然而,实习字符串存在一些缺陷。它们不是垃圾收集的,并且该方法本身有点贵。
答案 3 :(得分:0)
Java方法中的final
关键字不能按照您的想法执行。
在这种特殊情况下,final
使变量不可修改。而已。内容本身确实被添加到String常量的全局表中,但是指向它的指针(请原谅术语)在技术上每次都设置。
final
关键字在一个方法中主要用于使变量可用于您之后创建的任何匿名类。对于他们喜欢考虑“封闭”的东西,这是Java的糟糕的半支持。它也恰好是唯一方式,您可以从内部匿名类中访问外部变量。
final String bar = "Bar";
final Set<String> allTheBars = new HashSet<>() {{
add(bar);
}};