Skip to content

9. Stringhe in Java

Indice


9.1 Stringhe & Text Blocks

9.1.1 Stringhe

9.1.1.1 Inizializzare le stringhe

In Java, una String è un oggetto della classe java.lang.String, usato per rappresentare una sequenza di caratteri.

Le stringhe sono immutabili: una volta create, il loro contenuto non può essere cambiato. Qualsiasi operazione che sembra modificare una stringa in realtà ne crea una nuova.

Puoi creare e inizializzare le stringhe in diversi modi:

String s1 = "Hello";                    // string literal
String s2 = new String("Hello");        // using constructor (not recommended)
String s3 = s1.toUpperCase();           // creates a new String ("HELLO")

Note

  • I letterali stringa sono memorizzati nello String pool, un’area speciale di memoria usata per evitare di creare oggetti stringa duplicati.
  • L’uso della keyword new crea sempre un nuovo oggetto al di fuori del pool.

9.1.1.2 Lo String Pool

Poiché gli oggetti String sono immutabili e ampiamente usati, potrebbero facilmente occupare una grande quantità di memoria in un programma Java.

Per ridurre la duplicazione, Java riutilizza tutte le stringhe dichiarate come letterali (vedi l’esempio sopra), memorizzandole in un’area dedicata della JVM nota come String Pool o Intern Pool.

Per una spiegazione più approfondita e esempi, controlla il paragrafo: "6.4.3 String Pool and Equality" nel capitolo: Istanziazione dei tipi.

9.1.1.3 Caratteri speciali e sequenze di escape

Le stringhe possono contenere caratteri di escape, che permettono di includere simboli speciali o caratteri di controllo (caratteri con un significato speciale in Java).
Una sequenza di escape inizia con un backslash \.

Note

Tabella dei caratteri speciali & sequenze di escape nelle stringhe

Escape Significato Esempio Java Risultato
\" doppia virgoletta "She said \"Hi\"" She said "Hi"
\\ backslash "C:\\Users\\Alex" C:\Users\Alex
\n a capo (LF) "Hello\nWorld" Hello + line break + World
\r ritorno carrello (CR) "A\rB" CR before B
\t tab "Name\tAge" Name Age
\' virgoletta singola "It\'s ok" It's ok
\b backspace "AB\bC" AC (il B viene rimosso visivamente)
\uXXXX unità di codice Unicode "\u00A9" ©

9.1.1.4 Regole per la concatenazione di stringhe

Come introdotto nel capitolo su Operatori Java, il simbolo + normalmente rappresenta l’addizione aritmetica quando viene usato con operandi numerici.

Tuttavia, quando applicato alle String, lo stesso operatore esegue la concatenazione di stringhe — crea una nuova stringa unendo gli operandi tra loro.

Poiché l’operatore + può apparire in espressioni in cui sono presenti sia numeri sia stringhe, Java applica un insieme specifico di regole per determinare se + significa addizione numerica o concatenazione di stringhe.

9.1.1.5 Regole di concatenazione

  • Se entrambi gli operandi sono numerici, + esegue l’addizione numerica.
  • Se almeno un operando è una String, l’operatore + esegue la concatenazione di stringhe.
  • La valutazione è strettamente da sinistra a destra, perché + è associativo a sinistra.

Questo significa che, una volta che una String appare sul lato sinistro dell’espressione, tutte le successive operazioni + diventano concatenazioni.

Tip

Poiché la valutazione è da sinistra a destra, la posizione del primo operando String determina come viene valutato il resto dell’espressione.

  • Esempi
// *** Pure numeric addition

int a = 10 + 20;        // 30
double b = 1.5 + 2.3;   // 3.8



// *** String concatenation when at least one operand is a String

String s = "Hello" + " World";  // "Hello World"
String t = "Value: " + 10;      // "Value: 10"



// *** Left-to-right evaluation affects the result

System.out.println(1 + 2 + " apples"); 
// 3 + " apples"  → "3 apples"

System.out.println("apples: " + 1 + 2); 
// "apples: 1" + 2 → "apples: 12"



// *** Adding parentheses changes the meaning

System.out.println("apples: " + (1 + 2)); 
// parentheses force numeric addition → "apples: 3"



// *** Mixed types with multiple operands

String result = 10 + 20 + "" + 30 + 40;
// (10 + 20) = 30
// 30 + ""  = "30"
// "30" + 30 = "3030"
String out = "3030" + 40; // "303040"

System.out.println(1 + 2 + "3" + 4 + 5);
// Step 1: 1 + 2 = 3
// Step 2: 3 + "3" = "33"
String r = "33" + 4;  // "334"
// Step 4: "334" + 5 = "3345"



// *** null is represented as a string when concatenated

System.out.println("AB" + null);
// ABnull

9.1.2 Text Blocks (da Java 15)

Un text block è un letterale stringa multi-linea introdotto per semplificare la scrittura di stringhe grandi (come HTML, JSON o codice) senza la necessità di molte sequenze di escape.

Un text block inizia e termina con tre doppi apici (""").

Puoi usare i text block ovunque useresti le stringhe.

String html = """
    <html>
        <body>
            <p>Hello, world!</p>
        </body>
    </html>
    """;

Note

  • I text block includono automaticamente line break e indentazione per la leggibilità. I newline sono normalizzati a \n.
  • Le doppie virgolette all’interno del blocco di solito non richiedono escape.
  • Il compilatore interpreta il contenuto tra le triple virgolette di apertura e chiusura come il valore della stringa.

9.1.2.1 Formattazione: whitespace essenziale vs incidentale

  • Whitespace essenziale: spazi e newline che fanno parte del contenuto della stringa.
  • Whitespace incidentale: indentazione nel codice sorgente che non consideri concettualmente parte del testo.
String text = """
        Line 1
        Line 2
        Line 3
        """;

Important

  • Carattere più a sinistra (baseline): la posizione del primo carattere non-spazio su tutte le righe (o la """ di chiusura) definisce la baseline di indentazione. Gli spazi a sinistra di questa baseline sono considerati incidentali e vengono rimossi.
  • La riga immediatamente successiva alla """ di apertura non è inclusa nell’output se è vuota (formattazione tipica).
  • Il newline prima della """ di chiusura è incluso nel contenuto.
    Nell’esempio sopra, la stringa risultante termina con un newline dopo "Line 3": in totale ci sono 4 righe.

Output con numeri di riga (mostrando la riga vuota finale):

1: Line 1
2: Line 2
3: Line 3
4:

Per sopprimere il newline finale:

  • Usa un backslash di continuazione riga alla fine dell’ultima riga di contenuto.
  • Metti le triple virgolette di chiusura sulla stessa riga dell’ultimo contenuto.
String textNoTrail_1 = """
        Line 1
        Line 2
        Line 3\
        """;

// OR

String textNoTrail_2 = """
        Line 1
        Line 2
        Line 3""";

9.1.2.2 Conteggio righe, righe vuote e line break

  • Ogni line break visibile dentro il blocco diventa \n.
  • Le righe vuote dentro il blocco vengono preservate.
String textNoTrail_0 = """
        Line 1  
        Line 2 \n
        Line 3 

        Line 4 
        """;

Output:

1: Line 1
2: Line 2
3:
4: Line 3
5:
6: Line 4
7:

9.1.2.3 Text Blocks e caratteri di escape

Le sequenze di escape funzionano ancora dentro i text block quando necessario (per esempio, per backslash o caratteri di controllo espliciti).

String json = """
    {
      "name": "Alice",
      "path": "C:\\\\Users\\\\Alice"
    }\
    """;

Puoi anche formattare un text block usando placeholder e formatted():

String card = """
    Name: %s
    Age:  %d
    """.formatted("Alice", 30);

9.1.2.4 Errori comuni (con correzioni)

// ❌ Mismatched delimiters / missing closing triple quote
String bad = """
  Hello
World";      // ERROR — not a closing text block

// ✅ Fix
String ok = """
  Hello
  World
  """;
// ❌ Text blocks require a line break after the opening """
String invalid = """Hello""";  // ERROR

// ✅ Fix
String valid = """
    Hello
    """;
// ❌ Unescaped trailing backslash at end of a line inside the block
String wrong = """
    C:\Users\Alex\     // ERROR — backslash escapes the newline
    Documents
    """;

// ✅ Fix: escape backslashes, or avoid backslash at end of line
String correct = """
    C:\\Users\\Alex\\
    Documents\
    """;

9.2 Metodi principali delle stringhe

9.2.1 Indicizzazione delle stringhe

Le stringhe in Java usano l’indicizzazione a base zero, il che significa:

  • Il primo carattere è all’indice 0
  • L’ultimo carattere è all’indice length() - 1
  • Accedere a qualsiasi indice fuori da questo intervallo causa una StringIndexOutOfBoundsException

  • Esempio:

String s = "Java";
// Indexes:  0    1    2    3
// Chars:    J    a    v    a

char c = s.charAt(2); // 'v'

9.2.2 Metodo length()

length() restituisce il numero di caratteri nella stringa.

String s = "hello";
System.out.println(s.length());  // 5

L’ultimo indice valido è sempre length() - 1.

9.2.3 Regole dei limiti: indice iniziale vs indice finale

Molti metodi di String usano due indici:

  • Indice iniziale — inclusivo
  • Indice finale — esclusivo

In altre parole, substring(start, end) include i caratteri dall’indice start fino a (ma non includendo) l’indice end.

  • L’indice iniziale deve essere >= 0 e <= length() - 1
  • L’indice finale può essere uguale a length() (la “posizione virtuale” dopo l’ultimo carattere).
  • L’indice finale non deve superare length().
  • L’indice iniziale non deve mai essere maggiore dell’indice finale.

  • Esempio:

String s = "abcdef";
s.substring(1, 4); // "bcd" (indexes 1,2,3)

Questa regola si applica alla maggior parte dei metodi basati su substring.

9.2.4 Metodi che usano solo l’indice iniziale (inclusivo)

Metodo Descrizione Parametri Regola indice Esempio
substring(int start) Restituisce la sottostringa da start alla fine start start inclusivo "abcdef".substring(2) → "cdef"
indexOf(String) Prima occorrenza "Java".indexOf("a") → 1
indexOf(String, start) Inizia la ricerca all’indice start start inclusivo "banana".indexOf("a", 2) → 3
lastIndexOf(String) Ultima occorrenza "banana".lastIndexOf("a") → 5
lastIndexOf(String, fromIndex) Cerca all’indietro dall’indice fromIndex fromIndex inclusivo "banana".lastIndexOf("a", 3) → 3

9.2.5 Metodi con inizio inclusivo / fine esclusivo

Questi metodi seguono lo stesso comportamento di slicing: start incluso, end escluso.

Metodo Descrizione Firma Esempio
substring(start, end) Estrae una parte della stringa (int start, int end) "abcdef".substring(1,4) → "bcd"
regionMatches Confronta regioni di sottostringhe (toffset, other, ooffset, len) "Hello".regionMatches(1, "ell", 0, 3) → true
getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) Copia caratteri in un array di byte start inclusivo, end esclusivo Copia i caratteri in [srcBegin, srcEnd)
copyValueOf(char[] data, int offset, int count) Crea una nuova stringa offset inclusivo; offset+count esclusivo Stessa regola di substring

9.2.6 Metodi che operano sull’intera stringa

Metodo Descrizione Esempio
toUpperCase() Versione maiuscola "java".toUpperCase() → "JAVA"
toLowerCase() Versione minuscola "JAVA".toLowerCase() → "java"
trim() Rimuove whitespace iniziale/finale " hi ".trim() → "hi"
strip() Trim Unicode-aware " hi\u2003".strip() → "hi"
stripLeading() Rimuove whitespace iniziale " hi".stripLeading() → "hi"
stripTrailing() Rimuove whitespace finale "hi ".stripTrailing() → "hi"
isBlank() Vero se vuota o solo whitespace " ".isBlank() → true
isEmpty() Vero se length == 0 "".isEmpty() → true

9.2.7 Accesso ai caratteri

Metodo Descrizione Esempio
charAt(int index) Restituisce il carattere all’indice "Java".charAt(2) → 'v'
codePointAt(int index) Restituisce il code point Unicode Utile per emoji o caratteri oltre BMP

9.2.8 Ricerca

Metodo Descrizione Esempio
contains(CharSequence) Test di sottostringa "hello".contains("ell") → true
startsWith(String) Prefisso "abcdef".startsWith("abc") → true
startsWith(String, offset) Prefisso all’indice "abc".startsWith("b", 1) → true
endsWith(String) Suffisso "abcdef".endsWith("def") → true

9.2.9 Metodi di sostituzione

Metodo Descrizione Esempio
replace(char old, char new) Sostituisce caratteri "banana".replace('a','o') → "bonono"
replace(CharSequence old, CharSequence new) Sostituisce sottostringhe "ababa".replace("aba","X") → "Xba"
replaceAll(String regex, String replacement) Sostituzione regex globale "a1a2".replaceAll("\d","") → "aa"
replaceFirst(String regex, String replacement) Solo prima corrispondenza regex "a1a2".replaceFirst("\d","") → "aa2"

9.2.10 Suddivisione e unione

Metodo Descrizione Esempio
split(String regex) Suddivide per regex "a,b,c".split(",") → ["a","b","c"]
split(String regex, int limit) Suddivide con limite limit < 0 mantiene tutte le stringhe vuote finali

9.2.11 Metodi che restituiscono array

Metodo Descrizione Esempio
toCharArray() Restituisce char[] "abc".toCharArray()
getBytes() Restituisce byte[] usando encoding di piattaforma/default "á".getBytes()

9.2.12 Indentazione

Metodo Descrizione Esempio
indent(int numSpaces) Aggiunge (positivo) o rimuove (negativo) spazi dall’inizio di ogni riga; aggiunge anche un line break alla fine se non già presente str.indent(-20)
stripIndent() Rimuove tutto il whitespace iniziale incidentale da ogni riga; non aggiunge un line break finale str.stripIndent()
  • Esempio:
var txtBlock = """

                    a
                      b
                     c""";

var conc = " a\n" + " b\n" + " c";

System.out.println("length: " + txtBlock.length());
System.out.println(txtBlock);
System.out.println("");
String stripped1 = txtBlock.stripIndent();
System.out.println(stripped1);
System.out.println("length: " + stripped1.length());

System.out.println("*********************");

System.out.println("length: " + conc.length());
System.out.println(conc);
System.out.println("");
String stripped2 = conc.stripIndent();
System.out.println(stripped2);
System.out.println("length: " + stripped2.length());

Output:

length: 9

a
  b
 c


a
  b
 c
length: 9
*********************
length: 8
 a
 b
 c

a
b
c
length: 5

9.2.13 Esempi aggiuntivi

  • Esempio 1 — Estrarre [start, end)
String s = "012345";
System.out.println(s.substring(2, 5));
// includes 2,3,4 → prints "234"
  • Esempio 2 — Ricerca da un indice iniziale
String s = "hellohello";
int idx = s.indexOf("lo", 5); // search begins at index 5
  • Esempio 3 — Errori comuni
String s = "abcd";
System.out.println(s.substring(1,1)); // "" empty string
System.out.println(s.substring(3, 2)); // ❌ Exception: start index (3) > end index (2)

System.out.println("abcd".substring(2, 4)); // "cd" — includes indexes 2 and 3; 4 is excluded but legal here

System.out.println("abcd".substring(2, 5)); // ❌ StringIndexOutOfBoundsException (end index 5 is invalid)