本文是在jdk1.8的基础上解析的。
在JDK1.8中
调用 intern() 该方法:
如果常量池中 有 一个和当前对象相等 (用equals比较) 的字符串, 则返回常量池中的字符串 ;
否则把改字符串放到常量池中,并返回 该字符串的引用 .
一、实例解析1
String str1=new String("he")+new String("llo"); // 在堆中产生三个对象,str1 只指向合并后生成的那个"hello"对象;
String str2="hello"; // 在常量池中找,没有“hello”,所以在常量池中生成一个此常量对象,str2指向此对象,str2是常量对象的引用。
str1.intern(); // 在常量池中找,已经存在“hello”这个常量对象,故不生成常量引用.str1仍然指向堆中“hello”
System.out.println(str1==str2); // false // 两个对象的地址不一样,故false
String str1=new String("he")+new String("llo"); // 在堆中产生三个对象,string只指向合并后生成的那个"hello"对象;
str1.intern(); // 在常量池中找,没有“hello”这个常量对象,所以把字符串放到常量池并返回这个常量字符串的引用,和堆中那个对象的地址相同
String str2="hello"; // 常量池中已经存在这个常量对象的引用,所以str2指向这个引用,所以str2也指向str1对象
System.out.println(str1==str2);// true // 地址一样,内容一样,所以true
public static void main(String[] args) { String str1 = new String("1"); //首先此行代码创建了两个对象(如果常量池事先没有的话),在执行前会在常量池中创建一个"1"的对象引用,然后执行该行代码时 new 一个"1"的对象存放在堆区中;然后str1指向堆区中的对象; str1.intern(); //因为常量池中已经有常量“1”,故不会生成引用(即不改变str1的指向,str1仍然指向堆中对象)。 String str2 = "1"; // str2 是常量池中“1”的引用。故str1和str2指向不同 System.out.println(str1 == str2); //结果是 false }
public static void main(String[] args) { String str1 = "aaa"; String str2 = "bbb"; String str3 = "aaabbb"; String str4 = str1 + str2; String str5 = "aaa" + "bbb"; System.out.println(str3 == str4); // false String ss = str4.intern(); //如果常量池中 有 一个和当前对象相等 (用equals比较) 的字符串, 则返回常量池中的字符串,即使str4指向常量池中字符串的引用 System.out.println(str3 == ss); // true System.out.println(str3 == str5);// true }
public static void main(String[] args) { Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; System.out.println(c == d); //true System.out.println(e == f); //false System.out.println(c == (a + b));//true System.out.println(c.equals(a+b));//true System.out.println(g == (a + b));//true //包装类的“==”运行符在不遇到算术运算的情况下不会自动拆箱, // 以及他们的equals()方法不处理数据类型的关系, // 通俗的讲也就是 “==”两边如果有算术运算, // 那么自动拆箱和进行数据类型转换处理,比较的是数值等不等。 System.out.println(g.equals(a + b));//false // Long的equals方法会先判断是否是Long类型 }