Java加载字符串常量过程及==与equals区别

1. 引言

在学习Java_String类的过程中,判断字符串相等的==与equals实际运行结果不同,于是想查清为何,以及如何Java内存如何运作。特此记录提醒自己。

2. ==与equals

  • 对于基本数据类型,不需要引用的情况:包括boolean,byte,short,int,long,float,double等,彼此之间的判断可直接用==,为值的比较
  • 对于引用数据类型,如String类等,对于此类比较时,==为比较两者的内存地址。
  • equals来说,对于引用类型,默认也是比较其内存地址,但是大多经过重写,在lang包中一般将其重写为比较两者的值。

3. 示例代码

public class StringClassLearning {public static void main(String[] args) {//1.编译期间完成字符串拼接String str1 = "hello"+" JiangLian";String str2 = "hello JiangLian";System.out.println(str1 == str2);String str3 = "hello";String str4 = " JiangLian";String str5 = str3+str4;System.out.println("HashCode打印内存地址方法");/** str1: -669484201* str2: -669484201* str5: -669484201*/System.out.println("str1: "+str1.hashCode());System.out.println("str2: "+str2.hashCode());System.out.println("str5: "+str5.hashCode());System.out.println("identityHashcode打印内存地址方法");/** str1: 305808283* str2: 305808283* str5: 2111991224*/System.out.println(System.identityHashCode(str1));System.out.println(System.identityHashCode(str2));System.out.print(str5+"内存地址为");System.out.println(System.identityHashCode(str5));System.out.println(str2 == "hello JiangLian");System.out.println(str5 == "hello JiangLian");}}

代码所示:

  • str1与str2相等是由于编译器的遇到字符串常量之间的拼接时,做出优化,即在编译期间就会完成字符串的拼接,因此两者在运行时,引用类型数据指向的常量是一个。因此两者==为true
  • str5与str2不相等,执行过程为:内存执行过程icon-default.png?t=M276https://blog.csdn.net/hl_java/article/details/104497737
  1. 栈中开辟内存存放引用str3,str3指向常量池中的“hello”
  2. 栈中开辟内存存放引用str4,str4指向常量池中的“ JiangLian”
  3. 栈中开辟内存存放引用str5
  4. str3 + str4通过StringBuilder的最后一步toString()方法还原一个新的String对象"hello JiangLian",因此堆中开辟一块空间存放此对象。对应的内存地址变化
  5. 引用类型str5指向改新开辟的内存空间
  • 内存地址获取方法:
  1. hashcode获取地址,不是引用的真实内存地址,是经过String类重写过的hashcode,利用该方法获取地址,三者的内存地址相同,
  2. 通过System.identityHashCode(Object)判断三者的内存,确认==不同