Possible Duplicate:
How do I compare strings in Java?
为什么giving the following is the second队列比较S2 S3==true?什么是真的s2.tostring(回来)?(s2.toString())并置在哪里是真的吗?P></
- 我希望这是世界末日之前最后一次问这个问题;)
- @朋友,请不要!那就意味着世界末日快到了!
基本上,当使用EDCOX1(35)时,你强迫Java创建一个全新的对象。
当您分配给字符串文字="something"时,该字符串存储在常量池中,这是由JVM完成的优化。因此,当您将另一个引用分配给同一个常量时,存储在常量池中的对象将被重用,基本上,它是同一个对象。
- 注意:您不应该依赖这个特性,它只是实现细节。始终使用"foo".equals(otherString);进行比较
- @奥德拉?我?你能指出捷豹路虎吗?我想这是有保证的。
- 但事实并非如此,在当前的OracleJVM中,字符串international的长度可达6个左右。不确定。而且,您必须考虑各种lib,如javaassist、byteman等,它们也可能会处理字符串。依靠==和字符串只能带来麻烦。
- 信息:"所有文字字符串和字符串值常量表达式都是内部的。字符串文本在jls的&167;3.10.5中定义。还有这里
方法string.intern()可用于确保相等的字符串具有相等的引用。字符串常量是interned,因此s1和s2将引用同一字符串。String.toString()简单地返回自身,也就是说,当a是字符串时,a.toString()返回a。所以,s2也==s3。
一般来说,不应使用equals()通过引用相等,而是通过值相等来比较字符串。原因是很容易得到两个相等但引用不同的字符串。例如,在创建子字符串时。此规则的一个例外是,如果您知道这两个字符串都已预先过intern(或者作为比较的一部分,您对它们进行了实习)。
要回答关于堆或堆栈的隐含问题,将在堆上分配字符串。即使它们是在堆栈上分配的,例如在即将到来的转义分析和堆栈分配中,程序的语义也不会改变,您将获得相同的堆和堆栈分配结果。
首先,String.toString是一个禁止操作:
1 2 3 4 5 6 7 8
| /**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString () {
return this;
} |
第二,字符串常量是内部的,因此s1和s2在幕后被更改为相同的字符串实例。
- 难道这不是"字符串常量被实习生"?我怀疑来自一个文件或用户输入的字符串是被截取的。
- 正如您提到的,如果字符串足够长的时间挂起,来自不同输入的字符串可能会被拘留。这种不确定性就是为什么它通常更倾向于使用.equals。
- @没错,我更新了我的答案。
- @Mezmo:对,应该总是使用equals来比较字符串。你有没有一个关于"如果它们足够长时间的停留"的字符串的参考资料?
从Java虚拟机规格:
String literals and, more generally, strings that are the values of constant expressions are"interned" so as to share unique instances, using the method String.intern.
号
"andrei"是一个字符串文字,因此是"interned"。因此,字符串s1和s2都指同一个字符串对象,即内容为"andrei"的插入字符串。
因此,(s1 == s2) && (s1.equals(s2))为true。String#toString()并不创建新的String(与String中的许多其他方法一样),而是简单地返回this。前面的s2 == s3是true。
在比较Java字符串时,应该使用.Error和NO=。
==比较引用,因此s2.ToString()返回s2。
从Java词汇表看堆/堆栈:
1
| In Sun’s JVM, the interned Strings (which includes String literals ) are |
stored in a special pool of RAM
called the perm gen, where the JVM
also loads classes and stores
natively compiled code. However, the
intered Strings behave no differently
than had they been stored in the
ordinary object heap.
号
- 这是一个面试问题,我通常用等号。
- @安德烈·西奥巴努——它计算出,这些人问的问题,完全欺骗了程序员。
Why the first result is false ?
号
==比较引用并创建两个不同的对象。
I understood that for none primitive types, when we do '==',
号
字符串不是基元。当引用同一对象时,引用将是==。
比较s == s1时,您比较的是两个不同的MyString对象。这样想你的处境
。
s和s1是不同的对象,但它们的属性指向同一个toto实例。
它们是不同的对象,因为您创建它们的方式:
1 2
| MyString s = new MyString("toto");
MyString s1 = new MyString("toto"); |
因此,s == s1将返回false。为了让它返回true,它们必须是同一个对象。你可以这样做:
1 2
| MyString s = new MyString("toto");
MyString s1 = s; |
。
结果就是这样
氧化镁
MyString的每个实例都位于不同的内存位置,因此,忘记了实例的内容,对于每两个不同的实例,==测试将导致false。
对于String类,有一个很小但很重要的区别,当你分配一个String变量时,右手边的操作符是一个文本(即String s ="foo";),只有在以前没有遇到"foo"作为文本时,"foo"才会占用一个新的内存位置。如果是这种情况(即String s ="foo"; String otherS ="foo";),otherS只会引用已经存在的"foo"。
这种行为称为字符串池。
只有Interned(String.intern()字符串可以安全地与==进行比较,对于所有其他情况,您应该使用equals字符串。
在你的例子中,你定义了自己的类型EDCOX1,7,它与Java EDCOX1,3有很小的共同点,所以比较EDCOX1,9,EDCX1,10,你比较两个不同的对象的引用,这就是为什么你得到EDOCX1,11。
第一次比较失败的原因是,通过调用new创建了两个对象。现在,==操作符会比较两个内存地址,这会产生返回,因为这两个对象不在同一个内存单元中。
它使用常量字符串的原因是Java编译器EDCOX1(2),确实优化了代码。通过这种优化,相似的字符串常量被放置在同一个内存单元中。如果您执行了以下操作,那么对于您的String对象,结果将是相同的。
你的方法是。等于(其他)。为此,您必须在myString类中实现方法equals:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class MyString {
private String s ;
public MyString (String s ){
this. s = s ;
}
public String getContent (){
return s ;
}
@Override
public boolean equals (Object other ){
if(other instanceof MyString ){
MyString compareTo = (MyString ) other ;
return this. s. equals(compareTo. getContent());
}
return false;
}
} |
号
由于字符串是不可变的,ToString方法的一个有用的实现是(在String类中)返回这个值。
例如,my rt.jar包含以下实现:
1 2 3
| public String toString () {
return this;
} |
号
因此,与s3相关的参考与与与s2相关的参考相同。
考虑到s1==s2语句,这是由于所有常量字符串都自动调用intern()。这意味着在编译时,s2初始化代码将被s2=s1替换,这使得断言非常明显,不是吗?
- 嗯,是自动调用intern()还是编译时调用?
- 我倾向于认为这是编译时代码修改。
考虑到==比较引用,从s2 == s3可以看出,s2.toString()返回s2是正确的。
在字符串上使用==时,只比较引用。因此,只有在以下情况下,==才能保证返回true:
这里,s1 == s2。在所有其他情况下,即使两个字符串包含相同的字符序列,==也可以返回或不返回true。
要比较两个字符串的内容,请使用equals():
1 2 3
| if (s1.equals(s2)) {
...
} |
。
"=="是比较引用。但对象类中的equals()方法只是比较引用。子类中方法equals()的行为基于重写该方法的实现。
s2.ToString()正在返回字符串表示形式。因为它已经是一个字符串,所以它返回自己(这就是为什么比较是真的)。
所有字符串都分配在堆上,coparison运算符只是比较它们是否是同一个对象(这就是为什么s1!= S2)。
- 实际上,s1==s2为真。
- 啊,好的,那么我认为Java优化了它们,因为它们都引用相同的值。
- string s1="a";string s2="a"-s1==s2为真,for:string s1=new string("a");string s2=new string("a");s1==s2为假
- 是的,你是对的,还可以看到sting literal pools stackoverflow.com/questions/372547/…