java中==与equals比较两字符串的区别
在java中,我们经常会用到字符串的==与equals,这两者又有什么区别呢?
首先,我们先定义4个字符串,分别是:
~~~
String s1,s2,s3,s4;
s1 = new String("we are");
s2 = "we are";
s3 = s2;
s4 = new String(s1);
~~~
再分别对比下这几个字符串的异同:
~~~
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s1==s4);
System.out.println(s2==s3);
System.out.println(s2==s4);
System.out.println(s3==s4);
System.out.println("--------");
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s1.equals(s4));
System.out.println(s2.equals(s3));
System.out.println(s2.equals(s4));
System.out.println(s3.equals(s4));
~~~
得到的答案是:
~~~
false
false
false
true
false
false
--------
true
true
true
true
true
true
~~~
先来看一下==的,在这6个对比中,只有s2跟s3是相等的。要摸清楚原理,我们首先得了解java对象是如何定义的。
在java中,在java中,当一个对象被创建时,内存会为其分配一块空间,该对象的引用只是指向该内存。
再回头看看我们是怎么定义这4个字符串的:
1. s1 = new String("we are");这里s1的创建会在内存中分配一个空间。
2. s2 = "we are",很显然我们再创建了一个字符串值等于"we are",跟1的实现是一样的。
3. s3 = s2;这里相当于将s3指向s2所指向的那块内存地址。采用=号进行赋值,就是将s2所指向的那块内存地址赋值给s3。
4. s4 = new String(s1);在这里又要涉及到String类的原代码,我们看看String类的创建方法。
~~~
private final char value[];
private int hash; // Default to 0
public String() {
this.value = new char[0];
}
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
~~~
我们截取三个比较常见的构造方法和String所包含的两个变量。在这里我们可以看到,其实String类定义了一个char数组用来存储字符串的值,hash用于从缓存中找到该字符串。
1. String():该构造方法中将value设置为一个长度为0的数组。
2. String(String original):该构造方法传入了一个original的字符串,将该字符串里的value数组传递给新字符串的value数组。
3. String(char value[]):该构造方法传入了一个char类型的数组,新字符串将该串char数组复制到自己的value数组中。
以上三种方法创建的字符串都是新的字符串,拥有新的内存空间。
从这,可以看出,java中==的比较方式是比较两个变量是否指向同一个内存地址。
再来,我们看equals,这里面全部都返回true,这,我们可以大致确定,equals是比较字符串的内容了。看下以下源码:
~~~
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
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;
}
~~~
equals首先进行的是内存地址的比较,若都指向同一个地址,则返回true。接着判断是否是String类,最后比较两个字符串里面value数组的各个值,若相等,则返回true。
从这里,我们可以看出,String的equals比较的是value数组的值。