String的内存地址比较以及使用javap对其分析【基于JDK1.8】
- 首先来看下面一段代码,思考输出?
public static void main(String[] args) {
String strBase = "Rover";
String str0 = "Rover001";
String str1 = "Rover" + "001";
final String FINAL_STR = "Rover";
String str2 = new String("Rover");
String str3 = strBase + "001";
String str4 = FINAL_STR + "001";
String str5 = new String("Rover001").intern();
System.out.println(str0 == str1);
System.out.println(strBase == str2);
System.out.println(str0 == str3);
System.out.println(str0 == str4);
System.out.println(str0 == str5);
}
答案如下:
分析:
- 第一个true很好理解:String str0 = “Rover001” 分配在常量池中,String str1 = “Rover” + “001”;中的"Rover"和"001"也分别分配在常量池中,当出现"Rover" + “001"时,则会在常量池中寻找是否存在"Rover001”,此时str0和str1同时指向"Rover001";
- String str2 = new String(“Rover”);分配在堆中,而strBase存在于常量池中,故false;
- 这里的false需要结合以下的javap反编译class文件解释会更清晰:
图为使用以下javap命令对class文件反编译得到的:
E:\class\string>javap -v Intern.class
String str3 = strBase + “001”;实际执行过程是:先new出一个StringBuilder(参考图中24:),再调用StringBuilder的append()方法连接"001",最终执行toString()方法,并将所得值赋值给变量6(str3在Intern类中是第6个变量,参考图中43:astore 6),此时常量池中的str0和堆中的str3自然不相等;
4.分析同1.;
5.在JDK1.6中,intern()方法会把首次遇到的字符串实例复制到永久代(非堆)中,并返回永久代中该字符串实例的引用,在JDK1.7及以后,intern()方法不会再复制实例,只是将该字符串添加到常量池中、并返回其在常量池中的引用,此时,str0和new String(“Rover001”).intern()同指向常量池中的"Rover",因此返回true。
以下是常量池
E:\class\string>javap -v Intern.class
Classfile /E:/class/string/Intern.class
Last modified 2019-3-1; size 1441 bytes
MD5 checksum 4e6bbbf0fd149c40a0c2e838ce6c973d
Compiled from "Intern.java"
public class com.rover.javabase.baseclass.string.Intern
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #15.#42 // java/lang/Object."<init>":()V
#2 = String #43 // Rover
#3 = String #44 // Rover001
#4 = Class #45 // java/lang/String
#5 = Methodref #4.#46 // java/lang/String."<init>":(Ljava/lang/String;)V
#6 = Class #47 // java/lang/StringBuilder
#7 = Methodref #6.#42 // java/lang/StringBuilder."<init>":()V
#8 = Methodref #6.#48 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#9 = String #49 // 001