Rak*_*yal 184 java string string-interning
根据String #intern(),intern如果在String池中找到String,则该方法应该从String池返回String,否则将在String池中添加新的字符串对象并返回此String的引用.
所以我试过这个:
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}
if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}
Run Code Online (Sandbox Code Playgroud)
我期待s1 and s3 are same将被打印为s3被实习,并且s1 and s2 are same不会被打印.但结果是:两行都打印出来.这意味着,默认情况下,字符串常量被实现.但如果是这样,那么为什么我们需要这种intern方法呢?换句话说,我们什么时候应该使用这种方法?
Fil*_*eca 227
Java自动实习字符串文字.这意味着在许多情况下,==运算符似乎对字符串的工作方式与对int或其他原始值的处理方式相同.
由于对于字符串文字自动实习,因此该intern()方法将用于构造的字符串new String()
使用你的例子:
String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();
if ( s1 == s2 ){
System.out.println("s1 and s2 are same"); // 1.
}
if ( s1 == s3 ){
System.out.println("s1 and s3 are same" ); // 2.
}
if ( s1 == s4 ){
System.out.println("s1 and s4 are same" ); // 3.
}
if ( s1 == s5 ){
System.out.println("s1 and s5 are same" ); // 4.
}
Run Code Online (Sandbox Code Playgroud)
将返回:
s1 and s2 are same
s1 and s3 are same
s1 and s5 are same
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅JavaTechniques"String Equality and Interning".
Car*_*icz 20
在最近的一个项目中,一些庞大的数据结构被设置为从数据库读入的数据(因此不是字符串常量/文字),但是有大量的重复.这是一个银行应用程序,像一个适度的集(可能是100或200)公司的名称似乎到处都是.数据结构已经很大,如果所有这些公司名称都是唯一的对象,那么它们就会溢出内存.相反,所有数据结构都引用了相同的100或200个String对象,从而节省了大量空间.
实习字符串的另一个小优点是==可以使用(成功!)比较字符串,如果所有涉及的字符串都保证被实现.除了更精简的语法之外,这也是性能增强.但正如其他人所指出的那样,这样做会带来很大的引入编程错误的风险,所以这应该只是作为最后手段的绝对措施.
缺点是,实际生成String需要花费更多时间而不是简单地将其放在堆上,并且可能会限制实习字符串的空间,具体取决于Java实现.当你处理一个已知合理数量的字符串并且有很多重复时,最好这样做.
Ale*_*yak 14
我希望在使用==实习字符串时增加2美分.
首先要做的String.equals是this==object.
因此虽然有一些微不足道的性能提升(你不是在调用方法),但从维护者的角度来看,使用==是一场噩梦,因为一些实习字符串倾向于变成非实习.
所以我建议不要依赖于==实习字符串的特殊情况,但总是equals像Gosling那样使用.
编辑:实习成为非实习:
V1.0
public class MyClass
{
private String reference_val;
...
private boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
在2.0版本中,维护者决定hasReferenceVal公开,而没有详细说明它需要一个内部字符串数组.
V2.0
public class MyClass
{
private String reference_val;
...
public boolean hasReferenceVal ( final String[] strings )
{
for ( String s : strings )
{
if ( s == reference_val )
{
return true;
}
}
return false;
}
private void makeCall ( )
{
final String[] interned_strings = { ... init with interned values ... };
if ( hasReference( interned_strings ) )
{
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在你有一个可能很难找到的bug,因为在大多数情况下,数组包含文字值,有时使用非文字字符串.如果equals使用而不是==那时hasReferenceVal仍然会继续工作.再一次,性能提升微乎其微,但维护成本很高.
Boz*_*zho 12
默认情况下,字符串文字和常量是固定的.也就是说,"foo" == "foo"(由字符串文字声明),但是new String("foo") != new String("foo").
从设计上讲,Java中的字符串是不可变的对象。因此,两个具有相同值的字符串对象默认情况下将是不同的对象。但是,如果我们希望节省内存,则可以通过称为字符串实习生的概念来指示使用相同的内存。
以下规则将帮助您清楚地理解该概念:
例:
String s1=new String (“abc”);
String s2=new String (“abc”);
If (s1==s2) //would return false by rule #4
If (“abc” == “a”+”bc” ) //would return true by rules #2 and #3
If (“abc” == s1 ) //would return false by rules #1,2 and #4
If (“abc” == s1.intern() ) //would return true by rules #1,2,4 and #6
If ( s1 == s2.intern() ) //wound return false by rules #1,4, and #6
Run Code Online (Sandbox Code Playgroud)
注意:这里不讨论字符串实习生的动机情况。但是,节省内存无疑将是主要目标之一。