字符串的比较,不管在面试,或者是日常的开发中,都是经常会使用到的,本文将列举几种字符串的比较情况,先从简单的开始
1 equals的比较
1.1 下面的代码是true or false?
public static void main(String[] args){
String s1 = "a";
String s2 = new String("a");
String s3 = "a";
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
}
1.2 结果
答案都是true
1.3 为什么?
因为比较的是字符串的值
可以看下String的equals源码
public boolean equals(Object anObject) {
// 地址相等,返回true
if (this == anObject) {
return true;
}
// 被比较的也是字符串,才进行下一步判断,否则返回false
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
// 比较和被比较的字符串长度相等,才进行下一步判断,否则返回false
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
// 循环判断字符串的每个字符是否都相等
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
1.4 题外话
如果要忽略大小写,可以使用String.equalsIgnoreCase()进行字符串的比较
2 通过==进行比较
2.1 下面的代码是true or false?
public class Test01 {
public static void main(String[] args){
String s1 = "a";
String s2 = new String("a");
String s3 = "a";
System.out.println(s1 == s2);
System.out.println(s1 == s3);
}
}
2.2 结果
true
false
2.3 为什么?
通过==进行的字符串比较是通过地址进行比较,s1和s3通过字面量进行赋值,指向的是字符串常量池中的“a”,所以是true,而s2是通过new出来的String对象,所以和s1比较是false
2.4 拓展:String的intern方法
2.4.1 作用
将字符串对象放到常量池中
2.4.2 下面的代码是true or false?
public static void main(String[] args){
String s2 = new String("a") + new String("b");
s2.intern();
String s1 = "ab";
System.out.println(s1 == s2);
}
2.4.2 答案
jdk6 之前为false
jdk7/jdk8 之后为true
2.4.2 为什么
- jdk6情况下
s2会生成"ab"字符串对象,这个对象是在堆中的,intern方法会在常量池中在创建一个"ab"字符串对象(这个对象是在永久代的),所以jdk6情况下s1!=s2 - jdk7/jdk8情况下
s2会生成"ab"字符串对象,这个对象是在堆中的,intern方法也会将"ab"放到常量池中,但是jdk7之后字符串常量池移到堆中了,所以虚拟机有一个优化,调用intern方法在将“ab”放到常量池的时候,若堆中已经有"ab"这个字符串对象,那么并不会再创建一个"ab"字符串到常量池,而是将堆中的这个"ab"字符串对象的引用放到常量池,当有通过字面量直接赋值字符串变量的时候,返回的其实是堆中的同一个对象,所以jdk7/jdk8的环境下,s1==s2