字符串是我们编程时经常使用到的,但是其中的基本原理也是十分容易被忽略的。就像在Java中用到的String类型,我们几乎每天都会用到,但是其中的某些使用方法理解的还不是十分到位,下面通过自己在编程时碰到的一些坑分享下String中“==”与“equals”的异同。
两种不同的身份
我们知道在Java中String可以有两种不同的“身份”,一种是和普通劳苦大众一样都当做一个“对象”来看待,另一种是与int等一样当做一个基本类型。 如何区别一个String到底是哪种身份呢,我们可以从它的出身来看:
String s1 = new String("Hello word!");
String s2 = "Hello word!";
从上面两行代码来看,s1通过引用一个通过new的方式创造的一个对象,自然就是作为一个对象来使用;而第二种方式看起来更像声明一个int类型的变量,我们可以认为第二种方式将其作为一个基本变量来使用。
“==”与“equals”
为什么我们会提到String的两种不同身份呢,因为对应两种不同的的身份,它使用“==”和“equals”的结果也可能会完全不一样。
String对象
我们知道比较两个对象可以通过“==”和“equals”两种方式,但是这两种方式都有什么不同呢? 在Java中,最基本的类Object中包含有一个“equals”方法,具体的类继承自Object后可以重写该方法,String就做了这一点。 String将“equals”方法重写后,会对比两个字符串的内容,如果内容完全一致则返回“true”。而“==”则是通过对比两个对象的引用是否一致来判断,如果两个对象引用自同一个对象,即两个对象的引用指向同一内存块则判断为true,否则为false。
String s1 = new String("Hello word!");
String s2 = new String("Hello word!");
System.out.println(s1 == s2); //false
System.out.println(s1.equals(s2)); //true
通过上面的代码我们知道两个String类型的对象经管内容一样,但是它们的引用仍是指向两个不同的内存块,所以通过“==”比较后的结果是false,而equals方法对比的是String的字符串内容,则给出了肯定的回复。 再看下面这段代码相信大家的内心都不会有任何波澜了:
String s1 = new String("Hello word!");
String s2 = s2;
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
##String基本类型 当作为基本变量使用时,String的处理方式与“对象”身份时有所不同。 因为Java虚拟机的设定,当String作为基本类型来使用时,不会像对象那样每new一个新对象都会分配一个不同的内存块。作为基本类型,JVM的策略是这样的:
- 1.与普通对象不同,基本类型变量是保存在缓冲池中的;
- 2.新声明一个基本类型,如果缓冲池中不存在与其值相同的变量,则新创建一个变量并保存在缓冲池中;
- 3.如果缓冲池中已经包含一个变量并且与新声明的基本类型变量的值相同,那么JVM将不会创建一个新变量,而是直接返回该原有变量的引用。 了解了这些,我们就可以理解下面这4行代码及其返回值了:声明s1时缓冲池中没有值为”Hello Word!”的String类型变量,则新建一个并返回给s1该变量的引用,在创建s2时u缓冲池中检查,则发现有一个值为”Hello Word!”的变量,则直接将该变量的引用返回给s2,所以d
String s1 = "Hello Word!";
String s2 = "Hello Word!";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true