java String类型 ==与equal 浅析java中String类型中“==”与“equal”的区别
计通罗主任 人气:0一、前言
1.1、首先很多人都知道,String中用“==”比较的是地址,用equals比较的是内容,很多人对此用的是记忆法,通过记忆来加强此的引用,但是其真正的原理其实并不难,当我们真正明白其为什么的时候,用起来也会更加灵活,更加有底气(形容得不太好,朋友别见怪);
二相关知识的准备
- 类型常量池
- 运行时常量池
- 字符串常量池
我们今天讨论的主题是当然是字符串常量池:
为什么在这要把另外两个常量池拿出说一下呢,首先小生我在网上或者cnds上看到很多人在争论字符串常量池是存在与方法区还是堆里面,因此我在这里面非常负责任的告诉各位读者:
1、类型常量池,存放在方法区里面,每个class文件都有一个
2、运行时常量池、存放在方法区里面,所有class共用
3、字符串常量池:存放在堆区里面
而且字符串常量池有一个特点:存放的常量唯一:三、 开始
3.1,情况一
public class Test2 { public static void main(String[] args) { String a ="张敬轩"; String b ="张敬轩"; System.out.println(a == b); System.out.println(a.equals(b)); } }
运行结果:
- true
- true
解释:因为当我们String a = “张敬轩”;的时候,会在堆里面的字符串常量池里面“搜索”是否有“张敬轩”这个对象,
- 有:就会将“张敬轩这个对象的地址指向a”
- 没有:就会在字符串常量池里面新建立一个“张敬轩”,然后就会把地址引用赋值给a
当再声明String b = “张敬轩";和第一次声明String = “张敬轩”;一样,先”搜索“,然后因为已经存在了”张敬轩“这个对象,那么就不会再创建对象,而是将存在的”张敬轩“的地址引用赋值给b,所以
a和b的地址一样,内容自然也一样,所以两个结果为true,不懂各位朋友懂没懂?
3.2,情况二;
public class Test2 { public static void main(String[] args) { String a ="张敬轩"; String b = new String("张敬轩"); System.out.println(a == b); System.out.println(a.equals(b)); } }
结果是
false,true
解释
String a = “张敬轩”;
已经解释过了,是在堆里面的字符串常量池创建对象
String b = new String(“张敬轩”);
这个也是在堆区里面创建对象,但是不是在字符串常量池里面创建对象
两个不同的对象,地址自然不同,类容都是张敬轩,所以结果是false,true
3.3、情况三
public class Test2 { public static void main(String[] args) { String a = new String("张敬轩"); String b = new String("张敬轩"); System.out.println(a == b); System.out.println(a.equals(b)); } }
结果:false,true
解释,因为new (“张敬轩”);表示在堆区的非字符串常量池里面创建了两个不同的对象,两次new就创建了两个,所以地址是不同的,因此结果是false,true
3.4、情况四
public class Test2 { public static void main(String[] args) { String a = "张"+"敬轩"; String b = "张敬轩"; System.out.println(a == b); System.out.println(a.equals(b)); } }
结果是:true,true
解释:String = “张敬” + ”轩“;
在编译的时候就已经开始进行计算:这是Java编译的优化机制,所以a指向的地址依旧是”张敬轩“;所以情况和前面的情况一一致,所以是true,true
(注意Java编译优化机制只针对常量不针对变量 a = a+ b(这个是没有优化机制的,关于Java编译机制,各位小伙伴可以去百度了解一下))
3.5、情况五
public class Test2 { public static void main(String[] args) { String a = "张"; String b = "敬轩"; String c =a+b; String d = "张敬轩"; System.out.println(d == c); System.out.println(d.equals(c)); } }
结果:
解释:因为a 和 b是变量,不存在什么Java优化机制,而是将两个c = a + b存放在的是堆区的非字符常量池里面,所以是两个不同的对象,自然为false,true
3.6、最后一种情况
public class Test2 { public static void main(String[] args) { String a = "张"; String b = "敬轩"; String c =(a+b).intern(); String d = "张敬轩"; System.out.println(d == c); System.out.println(d.equals(c)); } }
结果:
解释:intern();方法是将堆区里面的非字符常量池里面的对象强行放到字符常量池里面,因为字符常量池里面对象的唯一性,如果字符串常量池里面已经有了和”张敬轩“一样的对象,就会将其地址引用赋值给c,没有就相当于创建一个(也就是和之前堆区里面那个对象一样的对象),有了的话,就会将原来有的那个“张敬轩”对象赋值给c,因为地址一样,所以为true
总结:
== 比较的地址 (如果对象存在字符串常量池,而且类容相同,那么 == 返回的是true )
equal 比较的是内容 (内容相同返回便是true)(所以在以后的开发中一般是用equal比较字符串的)
各位朋友如果有错的及时评论区指出,谢谢大家的支持
加载全部内容