Компилятор на этапе компиляции видит, что у вас в исходнике записаны две одинаковые строки и делает маленькую оптимизацию, которая, если выражать кодом, выглядит так:
String s0="Hello";
String s1=s0;
String s2=s0;
if(s1==s2)
System.out.println("yes");
else
System.out.println("no");
Здесь фактически в памяти существует одна строка и три ссылки на неё.
И пример с конструкторами:
String s0="Hello";
String s1=new String(s0);
String s2=new String(s0);
if(s1==s2)
System.out.println("yes");
else
System.out.println("no");
В этом примере используется конструктор, который копирует передаваемую в аргументе строку. Получается в памяти уже три объекта строки (с совпадающим контентом) и на них три отдельные ссылки. Так как ссылки указывают на разные объекты, то и результат их прямого сравнения выдаёт no.