その理由は、Stringリテラル"abc"
が、そのすべての出現に対してグローバルStringインスタンスに変換されるためです。これは、同じStringインスタンスになるため、確実に"abc" == "abc"
。Stringインスタンスは不変であるため、コンパイラがこれを行うことは可能です。ただし、文字列を明示的に割り当てると、それらは2つの異なるインスタンスになり、コンパイラによって暗黙的に作成された文字列インスタンスとは異なりnew String("abc") != new String("abc")
ます"abc" != new String("abc")
。
コンパイラが何をしているのかを理解するためのもう1つの良い例は、次のコードを調べることです。
"abc".contains("a");
リテラルが文字列型のインスタンスのように動作することがわかります。これを利用して、プログラミングエラーを最小限に抑えることができます。
// this is OK and the condition will evaluate to false
String myStringValue = null;
if ("abc".equals(myStringValue)) { // false
一方、このコードはNPEになります。
// this will produce a NPE
String myStringValue = null;
if (myStringValue.equals("abc")) { // NPE