这算是道难题,需要完全理解字符串的创建机制。 String s1 = new String("amit"); //这句在堆上创建了一个新的值为amit的字符串,用new创建是完全当做对象看待的。 System.out.println(s1.replace('m','r')); //此句话实际上相当于相当于在堆上创建了一个值为arit的字符串对象,然后打印到控制台。但没有让任何String引用指向它,所以短命的它将在下次垃圾回收时被回收。 System.out.println(s1); //s1依然指向着原来在堆上创建的amit字符串,所以输出amit String s3 = "arit"; //使用双引号创建字符串与用new完全不同,他会检测在栈中的字符串存储池中是否有值为arit的字符串,如果有则指向它,如果没有,则在栈中创建它;在第一句中虽然创建了一个值为arit的字符串,但是是在堆中创建的,不可共享。所以这里在栈中新建了一个arit字符串。 String s4 = "arit"; //如上所说,在存储池中查找到一个arit字符串,即s3指向的字符串,然后指向它,此语句其实并没有创建字符串,而是和s3指向了同一个字符串。这就是传说中的字符串共享。 String s2 = s1.replace('m','r'); //由于字符串是不可变的,所以这里的s1.replace('m','r')并不是把s1修改为arit,而是在堆中创建了一个新的值为arit的字符串,注意这里是在堆中创建的,而没有在栈中的字符串存储池中寻找arit然后共享,然后让s2指向了它。 System.out.println(s2); //输出了s1.replace('m','r');语句在堆中创建的值为arit的那个字符串。 System.out.println(s2 == s3); //理解了前面就理解了这个,虽然s2的值与s3一样都为arit,但是却没有实现共享机制,因为s2不是用s2 = “arit”的形式创建的,s2创建在堆中,而s3是创建在了共享池中。二者指向不同的对象,所以用==比较为false。 System.out.println(s3 == s4);//因为s3和s4都是在共享池中创建的,所以s3和s4实际上指向了同一个对象,所以用==比较为true。