Le stringhe sono il modo più comune per rappresentare testo nei programmi. In Java, gestire caratteri, simboli ed emoji in modo corretto è essenziale per evitare bug e sorprese. Con esempi chiari, vedremo come lavorare con caratteri singoli e sequenze di testo, quando scegliere API diverse e quali errori evitare.
In poche righe: imparerai cosa sono caratteri, stringhe e codice Unicode, come confrontare e manipolare il testo in sicurezza, quando usare StringBuilder, e quali pratiche evitare. Esempi concettuali ti aiutano a scrivere codice più chiaro, robusto e pronto per testi multilingue.
Come si rappresenta un carattere in Java?
In Java un singolo carattere si esprime con il tipo primitivo char e con apici singoli, per esempio 'A'. Internamente la piattaforma usa UTF‑16, quindi un char rappresenta un'unità di codice, non necessariamente un intero punto di codice Unicode.
Unicode definisce punti di codice fino a U+10FFFF; alcuni caratteri vengono codificati in UTF‑16 come coppie surrogate.
Testo originale
Unicode defines code points up to U+10FFFF; some characters are encoded in UTF-16 as surrogate pairs.
Esempio base
Il carattere '€' occupa una sola unità UTF‑16, mentre un'emoji come 😊 richiede due unità; il corrispondente escape Unicode è \uD83D\uDE0A. Per contare i veri caratteri visibili, considera i punti di codice e non solo la lunghezza in unità UTF‑16.
Se hai dubbi sui simboli internazionali, consulta una guida a Unicode per distinguere chiaramente unità UTF‑16 e veri punti di codice.
Qual è la differenza tra String e char[]?
Una String rappresenta una sequenza immutabile di testo; modificarla crea un nuovo oggetto. Un array char[] è modificabile e adatto a buffer temporanei. In Java, String è immutabile e char rappresenta un'unità UTF‑16 da 16 bit; di conseguenza alcune emoji richiedono due char per un solo simbolo.

L'immutabilità aiuta cache, sicurezza e prevedibilità, ma va evitata la creazione di copie superflue. Per dettagli formali, consultare la specifica del linguaggio Java. In scenari con dati sensibili (ad esempio password), preferisci char[] per poter azzerare esplicitamente la memoria dopo l'uso.
Quali operazioni su stringhe servono davvero?
Le API di String coprono dalla creazione al confronto, fino a ricerca, taglio e formattazione. Tra queste, il metodo equals per confronti affidabili è fondamentale; qui trovi ciò che risolve l'80% dei casi reali, con note su prestazioni e internazionalizzazione.
- Creazione: preferisci i letterali ("ciao") che entrano nel pool di stringhe. Usare new String("ciao") crea un oggetto in più, spesso inutile. Capire il pooling evita sprechi di memoria.
- Confronto: per il contenuto usa il metodo equals; == confronta i riferimenti. equalsIgnoreCase gestisce le maiuscole, ma attenzione a regole locali. Confronti lessicografici usano compareTo.
- Ricerca e verifica: contains, startsWith e endsWith sono chiari e leggibili. Per posizioni esatte usa indexOf/lastIndexOf. Ricorda che certe sequenze possono occupare due unità UTF‑16.
- Sotto-stringhe: substring non copia sempre i dati nelle versioni moderne, ma fai attenzione agli indici. Evita tagli in mezzo a una coppia surrogata o a una sequenza combinata.
- Divisione e unione: split usa regex, quindi i metacaratteri vanno eventualmente escapati. Per unire liste usa String.join o un StringJoiner, mantenendo il separatore coerente.
- Formattazione: String.format applica specificatori tipo %s o %.2f e rispetta il Locale. Per date e ore sfrutta le API dedicate, così separi formattazione e logica.
- Conteggio e iterazione: length restituisce unità UTF‑16, non sempre i caratteri percepiti. Usa codePointCount per contare i punti di codice e, se necessario, esegui normalizzazione prima dei confronti.
- Sicurezza e privacy: non loggare testi che contengono segreti; maschera o ometti. Quando devi gestire segreti temporanei, usa char[] per poter sovrascrivere i dati.
Testo e documenti
Nella pratica dovrai leggere e scrivere file di testo o integrare contenuti in documenti strutturati. Specifica sempre l’encoding atteso e verifica i risultati con testi multilingue; molte anomalie derivano da assunzioni errate sulla codifica.
Quando usare StringBuilder o StringBuffer?
La concatenazione ripetuta con "+" in un ciclo crea molte stringhe intermedie. StringBuilder evita questo overhead nelle sezioni single‑thread, mentre StringBuffer è sincronizzato e ha senso quando più thread modificano la stessa sequenza.

Se componi testo in iterazioni (ad esempio generando report), preferisci builder e unisci al termine. I compilatori ottimizzano le concatenazioni semplici in una singola espressione, ma nei cicli il builder resta la scelta più efficiente e leggibile.
Primi passi pratici
- Crea una String letterale.
- Estrai un char da una String.
- Concatena String in modo sicuro.
- Confronta String con equals.
- Usa StringBuilder per cicli.
Domande frequenti
Le stringhe sono mutabili in Java?
No. String è immutabile: ogni modifica produce un nuovo oggetto. Per costruzioni iterative usa StringBuilder; se serve sincronizzazione tra thread, valuta StringBuffer.
Perché length non coincide con i caratteri visualizzati?
length conta unità UTF‑16, non i punti di codice. Alcuni simboli (come emoji) occupano due unità. Per il numero di caratteri percepiti usa codePointCount e considera la normalizzazione.
Come confronto due stringhe ignorando maiuscole e minuscole?
Usa equalsIgnoreCase per confronti semplici. Per regole locali (ad esempio il turco) applica un Locale appropriato o normalizza prima del confronto per risultati più prevedibili.
Quando scegliere StringBuffer invece di StringBuilder?
Scegli StringBuffer quando più thread scrivono sulla stessa sequenza e desideri sincronizzazione integrata. In contesti single‑thread StringBuilder è più veloce e più semplice.
Come leggere correttamente testo da un file?
Indica esplicitamente il charset atteso e verifica i risultati con testi multilingue. Evita default impliciti della piattaforma: riducono la portabilità e possono introdurre caratteri errati.
Riepilogo e prossimi passi
- String è immutabile; char è un’unità UTF‑16.
- Conta i punti di codice quando lavori con emoji e simboli speciali.
- Usa equals per confrontare correttamente i contenuti di due stringhe.
- StringBuilder è ideale per concatenazioni iterative; StringBuffer per contesti multi‑thread.
- Gestisci encoding e normalizzazione per testi e documenti affidabili.
Hai visto come rappresentare caratteri, manipolare stringhe e scegliere gli strumenti adatti, dal confronto alla formattazione, fino alla composizione efficiente. Un’attenzione costante a Unicode e codifica evita sorprese con lingue e simboli diversi, migliorando la qualità di qualsiasi applicazione che tratta testo.
Per consolidare questi concetti, sperimenta con casi reali: testi multilingue, numeri formattati in vari Locale, concatenazioni in loop e gestione di input da file. Crea piccoli test automatici per ogni operazione critica: ti aiuteranno a mantenere il codice robusto e a prevenire regressioni quando l’applicazione cresce.
