Se a String é uma classe, então por que ao declararmos um objeto desse tipo, não utilizamos o new?

Por exemplo, por que pra declarar uma variável String nome = “Java” não usamos um new?

Como não?
Não acredite, apenas, no que você vê. Lembre-se, você tem um JRE por baixo dos panos.
Da mesma maneira, lembre-se de que toda e qualquer classe em que você não define uma superclasse explicitamente e quando você não define um construtor, o compilador entende, respectivamente que

public class Foo extends Object {}

E que

public class Foo {
    public Foo() {
        super();
    }
}

Basicamente, ao criar uma String desta maneira

String bla = "Blá blá blá";

Você está fazendo

String bla = new String("Blá blá blá");
1 curtida

A instrução new é utilizada para instanciar uma classe e não para declarar variáveis.
Acontece que a sintaxe do Java permite que você inicialize uma variável no mesmo momento em que a declara, então ao invés de escrever.

String nome;   // declarando
nome = "Java"; // inicializando

Você pode encurtar o código escrevendo:

String nome = "Java";  // declarando e inicializando

Não usa porque não quer, nada impede de você escrever:

String nome = new String("Java");

Acontece que o compilador Java é implementado de forma a tratar os literais entre aspas como sendo objetos do tipo String.
Além disso ele ainda é otimizado de forma que cada literal com o mesmo conteúdo seja uma instância do mesmo objeto.

Execute o exemplo abaixo para entender:

public class Exemplo {

    public static void main(String[] args) {
        Exemplo exemplo = new Exemplo();
        exemplo.semNew();
        exemplo.comNew();
    }

    private void semNew() {
        System.out.printf("Exemplo sem new%n");
        String a = "Java";
        String b = "Java";
        String c = "Java";
        testar(a, b, c);
    }

    private void comNew() {
        System.out.printf("Exemplo com new%n");
        String a = new String("Java");
        String b = new String("Java");
        String c = new String("Java");
        testar(a, b, c);
    }

    private void testar(String a, String b, String c) {
        System.out.printf("  referencia:%n");
        System.out.printf("    a == a:      %s%n", a == a);
        System.out.printf("    b == b:      %s%n", b == b);
        System.out.printf("    c == c:      %s%n", c == c);
        System.out.printf("    a == b:      %s%n", a == b);
        System.out.printf("    a == c:      %s%n", a == c);
        System.out.printf("    b == c:      %s%n", b == c);
        System.out.printf("  conteudo:%n");
        System.out.printf("    a.equals(a): %s%n", a.equals(a));
        System.out.printf("    b.equals(b): %s%n", b.equals(b));
        System.out.printf("    c.equals(c): %s%n", c.equals(c));
        System.out.printf("    a.equals(b): %s%n", a.equals(b));
        System.out.printf("    a.equals(c): %s%n", a.equals(c));
        System.out.printf("    b.equals(c): %s%n", b.equals(c));
    }
}
2 curtidas