今天公司上班期间因为一个equal使用发生了一场撕逼大战,下面先来讲述一下这场大战。
主角:
AAA为spm
BBB为程序猿
CCC吃瓜群众
序幕:BBB程序猿提交了如下代码,造成AAA的项目在使用中报停。
//add by BBB start
String accountName = rawContactDelta.getAccountName().equals("Phone") ?
getContext().getString(R.string.local_account_name) : rawContactDelta.getAccountName();
//add by BBB end
先不说这段代码的问题,继续看看这场撕逼大战。
AAA:为啥会这样写,自己写了,也不验证吗?
BBB:这么多模块开发,我编译了这个模块,代码没有问题啊?
AAA:问题是你弄出来的,下个版本由你来负责。
BBB: 你的意思怪我咯,那以后就叫别人帮你改这类问题哦,我太菜了!!
AAA: 这不是菜不菜的问题,这是你有没有check(验证的问题)。
BBB: 这么多模块,我哪里有时间验证这么多。
AAA:check很重要。
BBB:为了避免继续撕逼,弄得办公氛围紧张,会复了一个 ......
CCC:吃瓜群众全程观看不发言。
先来说一下报停的原因,是因为rawContactDelta.getAccountName()这个代码第一次执行时返回的结果为null,所以会报空指针异常。把他改成下面这样就不会出现:
//add by BBB start
String accountName = "Phone".equals(rawContactDelta.getAccountName()) ?
getContext().getString(R.string.local_account_name) : rawContactDelta.getAccountName();
//add by BBB start
这个写法也是Java推荐的写法。
我们不管这场撕逼大战谁对谁错,我们来看看equal使用,以及他与”==”的区别。
equals 方法是 java.lang.Object 类的方法。
使用说明:
(1)对于字符串变量来说,使用“==”和“equals()”方法比较字符串时,其比较方法不同。
“==”比较两个变量本身的值,即两个对象在内存中的首地址。“equals()”比较字符串中所包含的内容是否相同。
String str1,str2;
String str3 = "hello";
String str4 = "hello" ;
str1 = new String("hello");
str2 = new String("hello");
str1==str2 ?
str1.equals(str2) ?
这个两道题也是经常面试出现的,对于结果应该很明显。
str1==str2 结果为false,因为这是两个不同的对象,在内存中的地址不一样,故为false
str1.equals(str2) 是 true ,因为这个两个都是String对象,String类重写了equal()方法,比较的是所包含的内容,str1和str2包含的内容都是”hello”,故为true
注意(1):这里为啥强调两个对象是String类型,如果是Object类型,没有重写equal方法,比较的就不是内容,下面来看下面的例子:
StringBuffer s1 = new StringBuffer("hello");
StringBuffer s2 = new StringBuffer("hello");
s1.equals(s2) //结果是false
原因就是:StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类,而Object类中的equals方法是用来比较“地址”的,所以等于false.
注意(2)
str3==str4
结果是true,原因是str3和str4是两个字符串常量,其存放的内存地址是相等的,
s3=s4
str3==str4
返回结果也是true
(2)对于非字符串变量来说,”==”和”equals”方法的作用是相同的都是用来比较其
对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。
例如:
class Test
{
Test test1 = new Test();
Test test2 = new Test();
}
1.test1 == test2?
2.test1.equals(test2)?
答案都是false
原因:第一个是因为两个是不同对象,内存地址肯定不同。
第二个是因为Test类为Object,并没有重写equal方法,比较的是内存地址并不是所包含的内容。
但是如加上这样一句:test1=test2;
1. test1==test2?
2. test1.equals(test2)?
答案为true
下面来看看String中equals()方法源码:
public boolean equals(Object anObject) {
//判断当前对象(谁调用的equal()方法就是谁)与传入的对象(anObject)是否是同一个对象,如果相同则返回true
if (this == anObject) {
return true;
}
//如果两个对象不是同一个对象则判断传入的对象是否是字符串对象
if (anObject instanceof String) {
String anotherString = (String)anObject;//转化为String类型
int n = value.length;//当前对象的转化为value[](字符串数组)的长度
//如果当前对象转化为value[](字符串数组)的长度和传入对象转化为的value数组长度相等则继续比较每个字符是否相等。
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;//有个字符不同则返回false
i++;
}
return true;//字符全部相同返回true
}
}
return false;//不是同一个对象,不是字符串对象就直接返回false
}
所以总结一下:
equals方法对于字符串来说是比较内容的,而对于非字符串来说是比较
其指向的对象是否相同的。
== 比较符也是比较指向的对象是否相同的也就是对象在对内存中的的首地址。
String类中重写了equals这个方法,而且比较的是值,而不是地址。