0Pricing
Java Academy · Lezione

Immutabilità di String e string pool

Comprenda perché le String sono immutabili, come funziona lo string pool e quando utilizzare == invece di equals.

Immutabilità di String e string pool è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Immutabilità di String e String Pool

Le String sono immutabili in Java. Comprendere l'immutabilità, lo String Pool e la differenza tra uguaglianza dei riferimenti e uguaglianza dei valori aiuta a prevenire bug difficili da individuare.

Perché le String sono immutabili

Gli oggetti String non possono essere modificati dopo la loro creazione. Qualsiasi operazione che "modifica" una String crea in realtà un nuovo oggetto String. Questo consente la condivisione, la sicurezza dei thread e il caching di hashCode.

String s = "hello";
s.toUpperCase(); // creates a new String, does NOT modify s
System.out.println(s); // still "hello"

String upper = s.toUpperCase(); // must capture the result
System.out.println(upper); // HELLO

Lo String Pool (interning)

I letterali String vengono memorizzati nello String Pool (una sezione speciale dell'heap). Due letterali con lo stesso contenuto condividono lo stesso oggetto.

String a = "hello"; // goes into pool
String b = "hello"; // same object from pool
String c = new String("hello"); // forces new object outside pool

System.out.println(a == b);       // true  (same pool reference)
System.out.println(a == c);       // false (different objects)
System.out.println(a.equals(c));  // true  (same content)

== rispetto a equals()

Utilizzi sempre .equals() per confrontare il contenuto delle String. L'operatore == verifica se due variabili puntano allo stesso oggetto (uguaglianza dei riferimenti).

String input = new String("admin"); // from user input, not pooled
String role  = "admin";

// Dangerous: fails because different objects
if (input == role) System.out.println("Same"); // not printed!

// Correct: compares content
if (input.equals(role)) System.out.println("Equal!"); // prints

// Null-safe: put constant first to avoid NPE
if ("admin".equals(input)) System.out.println("Admin"); // prints

intern(): inserire manualmente una String nel pool

String.intern() inserisce forzatamente una String nel pool e restituisce il riferimento presente nel pool. Nelle versioni moderne di Java è raramente necessario.

String s1 = new String("interned");
String s2 = s1.intern();
String s3 = "interned"; // already in pool

System.out.println(s2 == s3); // true (both point to pool)
System.out.println(s1 == s3); // false (s1 is off-pool)

// Modern use: prefer String.intern() only when you need
// identity-based caching with thousands of repeated strings

Comportamento della concatenazione delle String

La concatenazione con + crea nuovi oggetti String. All'interno di un ciclo, ha complessità O(n²). Il compilatore ottimizza le singole espressioni, ma non la concatenazione basata sui cicli.

// Compiler optimizes this to a StringBuilder automatically:
String result = "Hello, " + "World" + "!";

// In loops: compiler does NOT optimize — use StringBuilder explicitly!
List<String> words = List.of("a", "b", "c", "d");
String bad = ""; // O(n^2) — new object each iteration
for (String w : words) bad += w;

StringBuilder sb = new StringBuilder();
for (String w : words) sb.append(w); // O(n) — efficient
String good = sb.toString();
System.out.println(good); // abcd

Confrontare correttamente le String

Utilizzi sempre equals(); per un confronto senza distinzione tra maiuscole e minuscole, utilizzi equalsIgnoreCase(). Utilizzi compareTo() per l'ordinamento lessicografico.

String a = "Java";
String b = "java";

System.out.println(a.equals(b));             // false
System.out.println(a.equalsIgnoreCase(b));   // true
System.out.println(a.compareToIgnoreCase(b)); // 0 (equal)
System.out.println(a.compareTo(b));           // negative (J < j in Unicode)

Caching di hashCode per String

Poiché le String sono immutabili, Java memorizza hashCode nella cache dopo la prima chiamata. Le chiamate successive restituiscono il valore memorizzato nella cache, rendendo le String molto efficienti come chiavi di HashMap.

String key = "product:12345";
// hashCode computed once and cached:
int h1 = key.hashCode();
int h2 = key.hashCode(); // returns cached value
System.out.println(h1 == h2); // true

// Strings are ideal HashMap keys because:
// 1. hashCode is consistent (immutable content)
// 2. hashCode is cached (fast repeated lookups)
// 3. equals is well-defined (content-based)
Map<String, Integer> map = new HashMap<>();
map.put("key", 42);
System.out.println(map.get("key")); // 42

String è final

La classe String è final: non può essere estesa. Questo garantisce che nessuna sottoclasse possa compromettere l'immutabilità o la coerenza di hashCode.

// String is final — this will not compile:
// class MutableString extends String {} // compile error

// You cannot override String behavior.
// If you need custom string-like behavior, use a wrapper:
record ProductSku(String value) {
    ProductSku { if (!value.matches("[A-Z]{3}-[0-9]{4}")) throw new IllegalArgumentException(); }
    @Override public String toString() { return value; }
}

String.format rispetto alla concatenazione

Per le stringhe composte da più parti, preferisca String.format() o i text block alla concatenazione, per maggiore chiarezza e una localizzazione più semplice.

String name = "Alice";
int age = 30;
double score = 97.5;

// Concatenation — harder to read with many parts
String bad = "User: " + name + ", Age: " + age + ", Score: " + score;

// String.format — clear placeholders
String good = String.format("User: %s, Age: %d, Score: %.1f", name, age, score);

System.out.println(good);
// User: Alice, Age: 30, Score: 97.5

Operazioni sulle String a prova di null

Molte operazioni sulle String generano una NPE se la stringa è null. Utilizzi approcci difensivi o String.valueOf() per gestire null in modo sicuro.

String value = null;

// Null-safe length check
int len = (value != null) ? value.length() : 0;
System.out.println(len); // 0

// Null-safe comparison (put constant first)
boolean isAdmin = "admin".equals(value); // false, no NPE

// String.valueOf converts null to "null" string
System.out.println(String.valueOf(value)); // "null"
System.out.println(Objects.toString(value, "default")); // "default"

Verifica rapida

Che cosa stampa il codice seguente?

String a = "hello";
String b = new String("hello");
System.out.println(a.equals(b));
System.out.println(a == b);

Riepilogo: immutabilità di String e String Pool

Punti chiave:

  • Le String sono immutabili: le operazioni restituiscono nuovi oggetti String e non modificano mai l'originale
  • I letterali String vengono inseriti nel pool: due letterali con lo stesso contenuto condividono un unico oggetto
  • Utilizzi sempre .equals() per confrontare il contenuto delle String; == confronta i riferimenti agli oggetti
  • Utilizzi equalsIgnoreCase() per i confronti senza distinzione tra maiuscole e minuscole
  • La concatenazione delle String nei cicli ha complessità O(n²): utilizzi StringBuilder per una maggiore efficienza
  • Le String memorizzano hashCode nella cache, risultando efficienti e sicure come chiavi di HashMap

Domande Frequenti

La lezione «Immutabilità di String e string pool» è gratuita?

Sì — il testo completo di «Immutabilità di String e string pool» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Immutabilità di String e string pool»?

Comprenda perché le String sono immutabili, come funziona lo string pool e quando utilizzare == invece di equals. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Immutabilità di String e string pool»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Immutabilità di String e string pool
  2. StringBuilder per concatenazioni efficienti
  3. Text block e String.format
  4. Espressioni regolari con Pattern e Matcher
← Torna a Java Academy