【Java】深层次解析字符串比较

字符串的比较,我一直以来也没做一个全面的总结,导致了自己对这块知识一知半解。
今天来全面的总结一下所有关于字符串的比较操作及原理

1. 字符串创建

在我们的JVM中,有常量池-存放字符串、堆-存放new的字符串、栈-存放引用地址

我们看一下创建字符串的两种方式:

		String s1 = "china";
        String s2 = "china";
        String s3 = "china";

        String ss1 = new String("china");
        String ss2 = new String("china");
        String ss3 = new String("china");
  • 对于第一种创建:在我们的常量池中创建出一个"china"的字符串,在栈中将s1、s2、s3指向其常量池

  • 对于第二种创建:首先去我们的常量池中寻找有没有"china"字符串,没有则创建,再去我们的堆进行对象的创建,在栈中将ss1、ss2、ss3指向堆中

  • 在这里插入图片描述

2. 字符串比较

2.1 普通比较

		String str1 = "a";
		String str2 = "b";
		String str3 = "ab";
		String str4 = str1 + str2;
		String str5 = new String("ab");
		String str6 = "a" + "b";

		System.out.println(str5.equals(str3));
		System.out.println(str5 == str3);
		System.out.println(str4 == str3);
		System.out.println(str5.intern() == str3);
		System.out.println(str5.intern() == str4);
		System.out.println(str5.intern() == str6);
		System.out.println(str3 == str6);

先想想自己的答案:

依次分析:
首先看下创建的过程

  1. String str1 = "a"; 直接常量池创建"a",栈创建str1指向
  2. 同上
  3. 同上
  4. String str4 = str1 + str2;,因为我们的JVM没有办法将str1和str2自动识别成字符串,所以会将他们new 一个放置在堆内存中
  5. String str5 = new String("ab");直接创建即可
  6. String str6 = "a" + "b";我们的JVM先将"a" + “b"变成"ab”,再去赋值给str6

比较过程:

前面的不说了,重点说一下关于:System.out.println(str5.intern() == str3);


官方API:

intern

public String intern()

返回字符串对象的规范化表示形式。

一个初始时为空的字符串池,它由类 String 私有地维护。

当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

所有字面值字符串和字符串赋值常量表达式都是内部的。

返回:一个字符串,内容与此字符串相同,但它保证来自字符串池中。


上面的理解比较官方,简单来说就是,我调用了这个函数,你给我返回一个存在于常量池中的字符串,要是没有,你给我加一个

比如:str5.intern()就是调用的常量池中的ab字符串,也就是只要指向ab字符串的,就可以判定为true

在这里插入图片描述

		System.out.println(str5.equals(str3));
		System.out.println(str5 == str3);
		System.out.println(str4 == str3);
		System.out.println(str5.intern() == str3);
		System.out.println(str5.intern() == str4);
		System.out.println(str5.intern() == str6);
		System.out.println(str3 == str6);

答案分别是:

true
false
false
true
false
true
true

2.2 final比较

看完上面的,是不是感觉自己超级牛逼,感觉啥都懂了
别慌 看这个

		final String str1 = "a";
		final String str2 = "b";
		String str3 = "ab";
		String str4 = str1 + str2;
		
		System.out.println(str4 == str3);

按照咱们上面说的,这个不细心的可能直接就false了

细心的看到对于str1和str2被final修饰了

回想一下,final修饰变量的作用,不可变性对吧。

如果被final修饰后,JNM在使用的时候,会把他当成一个字符串来使用,也就是类似于"a" + "b"这种操作,所以,最后的值是true

3. 总结

画图---->记住intern引用---->final变量
字符串比较不过如此~简简单单

猜你喜欢

转载自blog.csdn.net/qq_40915439/article/details/108437253