字符串判等整合

前言

字符串判等分很多情况,随着不断地加深学习,遇到了很多出乎意料的结果,在此做一个积累,便于日后添加和查阅。
#1、equals()和"=="二者的比较

public class EqualsPractice {
	/**
	 * 注:输出语句中,如果比较语句中不加两边的括号会把前面的文字吃掉,这是运算符优先级问题,
	 * 程序会先执行+,字符串拼接之后才会进行比较
	 */
	public void getSummary() {
		/*
		 * EqualsPractice中没有重写equal()方法,所以比较的是地址
		 */
		EqualsPractice c = new EqualsPractice();
		EqualsPractice c1 = new EqualsPractice();
		System.out.println("c.equals(c1):" + c.equals(c1)); //false

		/*
		 * String类中重写了equal()方法,所以比较的是字面量;而==比较的是地址
		 */
		String c2 = new String("abc"); //new String("abc")存放在堆中,c2存放在栈中(堆栈通常指栈)
		String c3 = new String("abc");
		System.out.println("c2.equals(c3):" + c2.equals(c3)); //true
		System.out.println("c2 == c3:" + (c2 == c3)); //false

		/*
		 * 常量比较中,"=="和equal()方法比较的都是地址
		 */
		String s = "abc"; //"abc"存放在常量池中,s存放在栈中
		String s1 = "abc";
		System.out.println("s == s1:" + (s == s1)); //true
		System.out.println("s.equals(s1):" + s.equals(s1)); //true
	}

	public static void main(String[] args) {
		EqualsPractice objSum = new EqualsPractice();
		objSum.getSummary();
	}
}

这是去年二月十六号第一次接触判等时记录的笔记,当时觉得自己终于掌握判等了,直到后来我才知道原来自己会的只是冰山一角。

2、String中的intern()方法

public void getSum() {
	/**
	 * 一个String变量调用intern()方法时,JVM查找常量池中是否有相同的字符串常量,
	 * 如果存在,会将等号左边的值指向常量池此地址,但是并不会改变等号右边原字符串的地址指向。
	 * 
	 * 注:输出语句中,如果比较语句中不加两边的括号会把前面的文字吃掉,这是运算符优先级问题,
	 * 程序会先执行+,字符串拼接之后才会进行比较
	 */
	String s0 = "上官海翰";
	String s1 = new String("上官海翰");
	String s2 = new String("上官海翰");
	System.out.println("s0 == s1:" + (s0 == s1)); //false:地址不一样,前者在常量池,后者在堆内存中
	
	s1.intern();
	s2 = s2.intern();
	System.out.println("s0 == s1:" + (s0 == s1)); //false:同上,因为s1.intern()改变的并不是s1的地址指向
	System.out.println("s0 == s1.intern():" + (s0 == s1.intern())); //true:因为s1.intern()改变的是s1.intern()整体的地址指向,指向的是常量池,这里说的就是上述的等号左边
	System.out.println("s0 == s2:" + (s0 == s2)); //true:同上,因为s2.intern()的结果赋值给s2了,所以s2的地址指向常量池,因此相等

	String s3 = new String("上官海翰");
	String s4 = s3.intern();
	System.out.println("s3 == s4:" + (s3 == s4)); //false:s3指向堆内存,s4指向常量池

	String s5 = "上官";
	String s6 = "海翰";
	String s7 = "上官海翰";
	String s8 = s5 + s6; // 在编译的时候,JVM并不知道s5+s6等于上官海翰,所以在运行的时候会new新的上官海翰,因此地址不一样
	String s9 = "上官" + "海翰"; //在编译的时候会自动合并成上官海翰,所以调用之前"上官海翰"的地址,因此地址一样
	System.out.println("s7 == s8:" + (s7 == s8)); //false
	System.out.println("s7 == s9:" + (s7 == s9)); //true
}

代码中的注解已经很清楚了,所以基本都不会有任何疑问。

以下是我当时产生的疑问:

String s3 = new String("上官海翰");
String s4 = s3.intern();
System.out.println("s3 == s4:" + (s3 == s4)); //false

可是如果单拿出这段代码运行,按照intern()方法的解释,在常量池并没有"上官海翰",难道JVM是在堆内存中又创建了一个对象,赋值为"上官海翰"并指向s4?
其实并不是这样的,这是JVM的一个机制,当创建一个对象并赋值时,会先去常量池查找是否有这个值,如果存在这个值,就复制一份到堆内存中,如果不存在这个值,会先在常量池创建这个值,之后复制一份到堆内存中。因此,常量池已经包含"上官海翰"了。

如果对JVM存储机制想详细了解,可以看这篇文章
https://blog.csdn.net/Marvel__Dead/article/details/69220153

3、总结

以上就是我对字符串判等的理解,如有不对之处,希望诸君不吝赐教。

版权声明:本文出自孤星卟哭的博客,原创文章,转载请注明出处。 https://blog.csdn.net/zcy92949/article/details/80074839

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值