我们来谈谈字符串比较问题。
首先,先举个例子:
String a="abc";
String b="abc";
String c=b;
String d=new String("abc");
String f=new String("abc");
首先我们要明白,每个对象都有自己的地址域和数据域。
什么是地址域呢?地址域就是存放当前对象的地址的内存单元。
什么是数据域呢?数据域就是存放当前对象的数据的内存单元。
像String a="abc"就是创建了一个String引用对象a 和 一个String常量"abc"。
引用对象a中的地址域存放的就是a本身的地址,而它的数据域存放的是
字符串常量"abc"的地址。而字符串常量"abc"的地址域存放的也是自身的地址,
而它的数据域存放的则是abc这个值。
所以,if(a==b)所表达的意思是,a的数据域的值和b的数据域的值是否相等,
也就是说a的数据域中所存放的地址和b的数据域中所存放的地址是否一致,
也可以说a和b是否指向同一块内存单元,很明显,a和b是指向同一块内存单元的。
那么String c=b是什么意思呢?
你可以理解为传统的赋值,也就是把b的数据域的值赋给c,那么c的数据域所存放的值也是"abc"的地址,那么c和b有什么不同呢?
它们的数据域是相同的,但地址域就不同了,当然了,引用对象本身的地址在java中比较少被用到,若是在c语言,c语言有多级指针的概念,也就是说在c语言中,还有可能有别的引用对象指向a,b等引用对象。
举个例子吧,可能存在一个引用对象e,它的地址域存放的是它自身的地址,它的数据域存放的是a的地址,而a的地址域也是它自身的地址,而且被复制了一份放到e的数据域中,且a的数据域所存放的是字符串常量"abc"的地址,而字符串常量"abc"的地址域存放的也是自身的地址,而它的数据域存放的则是abc这个值。
现在补充说一下什么是字符串常量,一般来说:
我们通过String a="abc";这样的方式来引用一个字符串对象,java底层是这样做的。首先去字符串常量池中查找,看有没有存在值为abc的字符串存在,有的话直接将常量的地址返回,没有存在的话就创建一个字符串常量,然后再将地址传返回,接着创建一个引用对象a用来接收返回的地址。
而如果通过String d=new String("abc");这样的方式来引用字符串对象,就不会去常量池查找了,而是直接在堆中开辟一块内存单元,内存单元的数据域就是abc,然后把这块内存单元的地址返回,然后在栈中创建一个引用对象d来接收地址。
所以,题目中用==比较的话,a,b,c是相等的,d和f也是相等的,其余就不等了。
而上面5个引用对象想表达的都是abc,要怎么才能让他们都相等呢?
这就需要equals()函数了,String类中有这么一个方法,就是通过String引用对象的数据域存放的地址,找到相应的内存单元,然后再把内存单元的数据域中的值取出来,当两个要比较的对象所指向的内存单元中的数据域中的值都取出来后,就可以比较他们是否相等了。这就是值的比较了,也就不会再比较地址了。
一般情况下,我们比较的都是它们的值,也就是if(a.equals(b))这种比较方式用得比较多,if(a==b)相对来说用得少些,当然这是针对字符串比较这问题来说的。
这是作者个人的理解,如果有不同看法,可以一起讨论讨论...