public static void main(String[] args) {
// 在常量池中创建"abc",s1指向常量池中"redis"的引用地址
String s1 = "abc";
// new String()在堆中开辟一块内存空间,将内存空间的地址引用赋值给s2,
// "abc"是常量,然后去字符串常量池查看是否有"abc"字符串对象,没有的话分配一个空间存放"abc",并且将其空间地址存入堆中new出来的空间中
String s2 = new String("abc");
// s1指向的是常量池中的地址,s2指向的是堆中地址,两个肯定不一样,false
System.out.println("s1==s2 " + (s1 == s2));
// String.intern()方法首先去查询常量池中是否有已经存在字符串"abc",
// 如果存在,则返回常量池中该字符串的引用;如果不存在,则在常量池中生成一个对原字符串的引用并返回
// 由于字符串"abc"在常量池中已经存在,所以s2.intern()返回的是"abc"在常量池中的地址引用,s2.intern() == s2 即为false
System.out.println("s2.intern()==s2 " + (s2.intern() == s2));
// s1和s2.intern()都是指向常量池中"abc"的地址引用,所以是true
System.out.println("s2.intern()==s1 " + (s2.intern() == s1));
// toString()方法会调用new String(),在堆中开辟一块内存空间,将内存空间的地址引用赋值给str,
// "计算机"是常量,然后去字符串常量池查看是否有"计算机"字符串对象,没有的话分配一个空间存放"计算机",并且将其空间地址存入堆中new出来的空间中
String str = new StringBuilder("计算机").toString();
// 因为常量池已经存在"计算机",所以str.intern()返回的是常量池中"计算机"的地址引用,而str指向堆中的地址引用,则两者是false
System.out.println(str.intern() == str); // false
// toString()方法会调用new String(),即在堆中创建一个String类的对象,内容是拼接后的"计算机软件",
// 注意:相加出来的结果,是不会被放到常量池中,常量池中没有字符串"计算机软件"
// str1指向堆中String类对象的地址引用
String str1 = new StringBuilder("计算机").append("软件").toString();
// str1.intern()首先去常量池中查找"计算机软件",没有找到,则将在堆上的地址引用复制到常量池,并将这个引用返回.
// str1.intern()和str1指向的都是堆中String类对象的地址,所以是true
System.out.println(str1.intern() == str1); // true
// str2指向堆中地址
String str2 = new StringBuilder("ja").append("va").toString();
// 由于JVM虚拟机在初始化的时候已经在常量池创建了"java",所以str2.intern()返回的是常量池中"java"的引用,则为false
System.out.println(str2.intern() == str2); // false
}
}