目前排名比较靠前的答案都回答得很浅显易懂了。
我这里给你一个最可靠的理论依据(虽然比较晦涩)。
Java语言规范(JavaSE 1.8版本)章节3.10.5中对此作了规范,因此所有的Java语言编译、运行时环境实现都必须依据此规范来实现。
里面有这么一句话Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
大意是:凡是内容一样的字符串常数,都要引用同一个字符串对象,换句话说就是内存地址相同。
原因是,其值为常量的字符串,都会通过String.intern()函数被限定为共享同一个对象。
具体也可以参考一下String.intern()函数的说明:String (Java Platform SE 8 )
上面的Java语言规范3.10.5里,还有一段代码例子。
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { public static String hello = "Hello"; }
produces the output:
true true true true false true
从这段例子可以看出,凡是编译期能推断出值内容的字符串,都会在编译时变成字符串常量,从而享有上面提到的共享对象的待遇。而运算中间插入了变量,让编译器认为只有运行时才能判断其内容的字符串,则会在运行时产生新的对象。(倒数第二个输出false的情况。)
计算机世界的东西就是这样的,有人定下了规矩,大家就都得照规矩办。毕竟整个计算机世界都是人造出来的,也就是这个帝国是由人类的规矩构建的,无论这个规矩是合理的还是不合理如键盘排布,一旦定下来也就不得不遵从了。
于是,就出现了你提问中的现象。说白了,做Java的人强制如此的。当然,从规矩产生的原因上说,这个规矩是有利于改善性能的。