package com.jvm;
import org.junit.Test;
/**
* 常量池StringTable的详解
* 可以使用该命令查看,当前类的字节码常量池信息
* javap -v StringTableTest.class
*
* @author shiye
* @date 2020-05-04 13:13
*/
public class StringTableTest {
@Test
public void test1() {
String s1 = "a";//放到常量池中
String s2 = "b";//放到常量池中
String s3 = "ab"; //放到常量池中
/**
* 首先创建一个StringBuilder对象 然后从常量池中获取一个"a",然后再从常量池中获取一个"b"对象
* 然后再在堆中创建一个 new String("ab") 对象
* new StringBuilder().append("a").append("b").toString();
* --> toString()方法就是 new String("ab");
*/
String s4 = s1 + s2; //放到堆中
System.out.println(s3 == s4); //一个在堆中,一个再常量池中 false
/**
* ldc #4 // String ab 直接从常量池中获取 "ab"
* 这是javac在代码编译时的优化操作
* 会把 "a"+"b" 优化成 "ab",然后从常量池中查找
*/
String s5 = "a" + "b"; //放到常量池中
System.out.println(s3 == s5); // true
}
/**
* 首先常量池中有 ["a","b"] 俩个对象
* s.intern() 会把堆中创建的 "ab" 对象放到常量池中,如果常量池中有"ab"了 ,
* 则不会放到常量池中,但是一定会返回常量池中的对象
* <p>
* 对比:test2和test3
*/
@Test
public void test2() {
String s = new String("a") + new String("b");
String s2 = s.intern();
System.out.println(s2 == "ab");// true
System.out.println(s == "ab");//true
}
@Test
public void test3() {
String x = "ab"; //常量已经有了“ab” 就不会再放进去了
String s = new String("a") + new String("b");
String s2 = s.intern();
System.out.println(s2 == "ab");// true
System.out.println(s == "ab");//false
}
}
来源:oschina
链接:https://my.oschina.net/u/3677987/blog/4264827