我们知道Java的==比较的是地址,想要比较内容通常要用(override过的)equals方法。
但是对于以下这样的代码
String s1 = "qwq";
String s2 = "qwq";
boolean b = (s1 == s2);
b的值通常是true。
这是因为Java有常量池的机制,会把一些使用过的常量放进常量池,再使用时就不用再创建,而可以直接用常量池里的。引入常量池是为了提升Java的性能/效率,避免反复创建和销毁同一个对象。
除了String的常量池外,Java对float和double之外的基本类型的包装类(Integer等)都支持了常量池。通常来说,值在-128到127以内的Integer等类型都会放到常量池中,因为这些比较小的数最经常用到;其他的值就只能直接创建。浮点类型是没有常量池的。
String的常量池比较特别。一般来说,字符串字面值常量会放到常量池中;但new出来的字符串不会。不过,Java支持运行时常量池。虽然new出来的字符串不在常量池中,但String有intern()方法,调用之后会把字符串放入运行时常量池,同时返回池内字符串的引用。
比如对于以下代码
String s1 = new String("qwq");
String s2 = s1.intern();
String s3 = "qwq";
boolean b1 = (s1 == s2);
boolean b2 = (s2 == s3);
b1的值一般是false,b2的值一般是true。