概述
Java内存分析中,我们会经常听到关于“常量池”的描述,实际上常量池也分了以下三种:全局字符串常量池、class 文件常量池、运行时常量池(Runtime Constant Pool)。我们只关注常量池(Runtime Constant Pool)即可。
String类详解
线程有线程池来管理,而常量池就是为了来管理字符串的,所以这里必须要先熟悉String类。
相关网址:
Java String类(超级详细!)_长头发的程序猿的博客-CSDN博客
常量池详解
先看一段代码:
package org.example.test;
public class PoolTest {
public static void main(String[] args) {
String s1 = "程序猿你好!!!";
String s2 = "程序猿你好!!!";
String s3 = new String("程序猿你好!!!");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s3));
}
}
运行结果:
下面我们来逐条分析:
1、s1 == s2
能来研究JVM的常量池的程序猿们肯定知道”==“比的是两个对象的内存地址,那么为什么“s1 == s2"的输出结果为true呢?
分析:
这就是常量池的原因,常量池它本身是一种管理字符串的机制,当我们执行“String s1 = "程序猿你好!!!";”时,jvm就会在常量池中开辟一块空间来存放s1,当执行到“String s2 = "程序猿你好!!!";”时,jvm就不会为s2开辟空间了,所以说“s1 == s2"的输出结果为true。
所以通过这个案例也能很好的理解”==“比的是两个对象的内存地址。
2、s1 == s3
分析:
“String s1 = "程序猿你好!!!";”在上面也说过了,jvm会在常量池中开辟一块空间来存放s1。
那我们主要来分析”String s3 = new String("程序猿你好!!!");“,在此之前必须要了解JVM内存区域”栈“和”堆“。
JVM内存区域相关网址:
”String s3 = new String("程序猿你好!!!");“会在”栈“中开辟一块空间来放s3,在”堆“中开辟一块空间来放new出来的对象”程序猿你好!!!“。而”==“比较的内存地址,所以很明显”s1 == s3“的结果为false。
3、s1.equals(s3)
equlas源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
先来分析”this == anObject“:
this指的就是”s1.equals(s3)“中的s1,anObject指的是s3,前面也说了”==“指的是内存地址,所以“s1.equals(s2)”返回的肯定也是true,这里感兴趣的自己可以去试一下。
再来分析”anObject instanceof String“:
instanceof是用来判断s3是否为String,可以看出equals比较的都是String字符串。
再看里面的内容,它先会使用”n == anotherString.value.length“来判断两个字符串的长度是否相同,再看下面的”value“和”while“这两个关键字,相信有点基础的小伙伴就可以凭借这两个关键字看出这是通过while循环比较这两个相同长度的字符的value值是否相同,由此可见,equals的主要作用就是比较两个String字符串的长度和值是否相同。
而s1.equals(s3)中,s1(程序猿你好!!!)和s3(程序猿你好!!!)的长度和值都是相同的,所以输出结果是true。