一、字符串比较
Java虚拟机中含有字符串池(直接量在此池内),相同内容的字符串直接量->相同的对象。
字符串比较方法有:
boolean equals(Object anObject)
比较当前的字符串与指定的对象。 比较结果为真当且仅当给定的参数不为空,并且具有完全相同的字符序列。
例如: s1.equals( "Hi" );
boolean equalsIgnoreCase(String anotherString),
判别相等,但不区分大小写。 例如: 在不区分大小写情况下, “hello”与“HELLO”相等。
int compareTo(String anotherString)
比较两个字符串的内容
返回: 0 : 如果字符串内容完全相同。
小于0的值: 如果在比较第一个不相同字符,当前字符串的字符的值小于anotherString对应的字符的值。
大于0的值: 如果在比较第一个不相同字符,当前字符串的字符的值大于anotherString对应的字符的值。
int compareToIgnoreCase(String str) 比较两个字符串的内容,但不区分大小写。
我们这里介绍的是intern方法:
方法intern
返回具有相同内容的字符串的引用。 如果字符串池含有该内容的字符串,则返回字符串池中具有该内容的字符串的引用。 如果字符串池没有字符串的内容与其相同,则在字符串池中创建具有该内容的字符串,再返回新创建的字符串的引用。
字符串池
组成: 字符串直接量以及由方法intern产生的字符串。 字符串池中的字符串s与t : s与t具有相同内容(s.equals(t))当且仅当指向s与t的同一个字符串(s.intern() == t.intern())。<->(也可以说成是字符串集合里面包含字符串直接量,有限个字符串直接量进行“+”运算的结果,以及java.lang.String的成员方法intern创建的字符串实例对象)
可以采用这个机制加速字符串是否相等的判定。
JDK 1.7后,intern()方法还是会先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用; 如果在常量池找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用。
这里我们注重的是学会判断比较,所以就先来一个实例分析:
public class String
{
public static void main(String []args)
{
String s1 ="123456";
String s2 ="123456";
String s3 ="123"+"456";
String a0 = "123";
String s4 = a0+"456";
String s5 = new String("123456");
String s6 = s5.intern();
System.out.println(s2==s1);
System.out.println(s3==s1);
System.out.println(s4==s1);
System.out.println(s5==s1);
System.out.println(s6==s1);
}
}
那么,你觉得输出结果是什么呢?
答案是:
true |
true |
false |
false |
true |
好的,我们来分析一下为什么是这样的。
在上面的例程中,字符串变量s1和s2均指向字符串直接量。字符串直接量位于字符串池中,位于字符串池中的具有相同序列的字符串只对应一个字符串实例对象。因为变量s1和s2指向的字符串直接量具有相同的字符序列,所以变量s2和s1指向的字符串对象实际上是同一个字符串对象,从而“s2==s1”为true。
变量s3指向的字符串是由有限个字符串直接量通过“+”运算得到的结果,所以变量s3指向的字符串序列位于字符串池中,又因为s3和s1指向的字符串直接量具有相同的字符序列,所以变量s3和s1指向的字符串对象实际上是同一个字符串对象,所以“s1==s3”为true。
变量s4指向的字符串是由变量a0与一个字符串直接量通过"+"运算得到的结果。虽然变量a0指向一个字符串直接量,但是变量a0本身不是字符串直接量,因此,变量s4指向的字符串不满足字符串直接量的定义,所以变量s4指向的字符串对象不再字符串池中。而变量s1指向的字符串直接量位于字符串池中,所以s4和s1不可能指向相同的字符串对象,从而输出false。
同样的,s5指向的字符串对象不在字符串池中,所以变量s5和s1不可能指向相同的字符串对象。所以输出false.
因为变量s6指向的字符串对象是通过类java.lang.String的成员方法intern得到的,所以s6指向的字符串对象在字符串池中,因为s6和s1具有相同的字符序列,并且都在字符串池中,所以变量s6和s1指向的字符串对象实际上是同一个字符串对象,从而输出true。
当然,这个理解不一样,你也可以从堆栈来理解,但是如上的理解也是正确的,为了验证你是否掌握了,有如下的测试:
public static void main(String []args)
{
String s1 ="abc";
String s2 = "abc";
System.out.println(s1==s2);
}
答案是:
true
public static void main(String[]args) {
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1==s2);
}
答案是:
false
public static void main(String[]args) {
String s1 = new String("abc");
String s2 = new String("a");
String s3 = new String("bc");
String s4 = s2 +s3;
System.out.println(s1==s4);
}
答案是:
false
public static void main(String[]args) {
String s1 = new String("abc");
final String s2 = "a";
final String s3 = "bc";
String s4 = s2 +s3;
System.out.println(s1==s4);
}
答案是:
false
public static void main(String[]args)
{
String s = new String("abc");
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s==s1.intern());
System.out.println(s==s2.intern());
System.out.println(s1==s2.intern());
}
答案是:
false
false
true
总结:
如果上面的测试你都对了,那么你理解的就很好了,如果还没有,再去看看例题分析吧。如有误,评论指出,谢谢。