Bom dia Marcos,
A classe String é uma classe especial em qualquer linguagem de programação OO, justamente por ser um tipo de dado muito, mas muito usado.
Em Java, por exemplo, é possível trabalhar com Strings sem necessariamente usar a palavra-chave new para instanciá-las. Isso não significa que com qualquer outro objeto vai funcionar. Se você pegar um objeto BigDecimal por exemplo, não conseguirá trabalhar sem explicitamente instanciá-lo.
O Java oferece essa facilidade na classe String devido ao largo uso dela, e a diferença de dar new em String ou não é a seguinte:
Quando você cria uma String com new, foi instanciado um objeto e alocado em memória num espaço exclusivo (como se você tivesse instanciado um BigDecimal, uma classe que você criou Conta, Produto, qualquer um do tipo), aquela instância tem acesso aos atributos e métodos que uma classe daquele tipo deve ter.
Quando você vai comparar dois objetos String que foram criados desta forma, o operador == não está olhando para o valor da String, ou para os valores do BigDecimal, ou do Produto, está olhando para a referência do objeto na memória, e comparando se são os mesmos objetos. Por isso que no caso de instanciar Strings com new e comparar com == vai dar falso, são dois objetos distintos na memória. (O operador == compara valor apenas dos primitivos, para objetos exclusivos compara referência).
Quando você cria uma String só atribuindo valor a ela, por trás o Java fez um objeto String normal, que terá acesso a todos os métodos públicos da classe e etc. Contudo, as Strings criadas desta forma são tratadas de forma diferenciada na memória pela JVM, e quando você utiliza o == nelas para comparação, o Java consegue realizar a comparação dos valores lexicograficamente (que seria da mesma forma que o equals() da classe String trabalha). Com isso o resultado vai dar verdadeiro.
No seu exemplo de código, note que se você comparar s1 (String criada com new) == s3 (String criada só com atribuição de valor), vai dar falso, porque a comparação acabará sendo pela referência ao objeto, e como são dois objetos distintos em memória, por mais que contenham o mesmo valor, não são o mesmo objeto.
Espero que tenha ficado claro que isso é uma situação exclusiva da classe String, outras classes (inclusive todas que você criar) precisarão do new para serem utilizadas.
Abraços.