Java — Cheat Sheet

Tag: java, jvm, oop, multithreading, collections, streams, backend

Livello: intermedio

TL;DR: Sintesi dei concetti core di Java, gestione della memoria (GC), multithreading e Stream API, ottimizzata per risposte rapide nei colloqui backend.

Concetti chiave

JVM, JRE, JDK: JVM esegue il bytecode, JRE fornisce le librerie a runtime, JDK include i tool di sviluppo (compiler, debugger).

Garbage Collection (GC): Gestione automatica della memoria nell'heap. I principali algoritmi sono G1GC (default da Java 9) e ZGC (low latency).

Passaggio di parametri: In Java il passaggio è sempre *per valore*. Per gli oggetti, viene passato per valore il riferimento (pointer) all'oggetto.

String Pool: Area della memoria heap dove vengono memorizzate le stringhe letterali per ottimizzare l'uso della memoria (String interning).

Immutabilità: String è immutabile. Per manipolazioni pesanti usare StringBuilder (non thread-safe) o StringBuffer (thread-safe).

Collections Framework: Gerarchia basata su List (ordinata, ammette duplicati, es. ArrayList), Set (non ordinata, no duplicati, es. HashSet), Map (chiave-valore, es. HashMap).

Concurrent Collections: Versioni thread-safe ottimizzate, come ConcurrentHashMap (lock segmentato) o CopyOnWriteArrayList.

Stream API: Operazioni funzionali sulle collection. Si dividono in *intermediate* (lazy, es. map, filter) e *terminal* (triggerano l'esecuzione, es. collect, reduce).

Multithreading: Creabile via Thread o Runnable. Preferire sempre l'ExecutorService o i thread pool per la gestione del ciclo di vita.

Eccezioni: Checked Exceptions (estendono Exception, devono essere dichiarate nel throws o catturate) e Unchecked Exceptions (estendono RuntimeException, non richiedono catch obbligatorio).

Domande tipiche e risposte pronte

Q: Qual è la differenza tra == e .equals()?

R: == confronta i riferimenti in memoria, quindi verifica se le due variabili puntano allo stesso oggetto. .equals() è un metodo sovrascrivibile usato per confrontare il valore logico e il contenuto degli oggetti.

Q: Come funziona internamente una HashMap in Java?

R: Usa un array di bucket. Calcola l'hash della chiave per trovare l'indice. In caso di collisioni (stesso hash), usa una LinkedList nel bucket. Da Java 8, se la lista supera 8 elementi, si converte in un albero Red-Black per mantenere performance O(log n).

Q: Differenza tra Abstract Class e Interface?

R: Una classe astratta può avere stato (variabili d'istanza) e costruttori, ma non supporta l'ereditarietà multipla. Un'interfaccia (da Java 8 con metodi di default/statici) definisce contratti e permette l'ereditarietà multipla dei tipi, ma non ha stato.

Q: Cos'è un memory leak in Java e come può accadere se c'è il GC?

R: Avviene quando oggetti non più usati logicamente mantengono riferimenti forti, impedendo al GC di eliminarli. Spesso causato da cache statiche non svuotate, listener non deregistrati o ThreadLocal non puliti.

Q: Qual è il contratto tra hashCode() e equals()?

R: Se due oggetti sono uguali secondo equals(), devono restituire lo stesso hashCode(). Se restituiscono lo stesso hash, non sono necessariamente uguali, ma andranno nello stesso bucket in una Hash table.

Insidie e errori comuni

Usare Double o Float per calcoli finanziari o di valuta. Usa sempre BigDecimal per evitare errori di precisione nel floating point.

Dimenticarsi di chiudere le risorse (stream, connessioni DB). Usa sempre il costrutto try-with-resources.

Modificare una collection mentre ci si sta iterando sopra con un ciclo for-each (causa ConcurrentModificationException). Usa un Iterator esplicito o rimuovi con removeIf.

Abuso del blocco synchronized su metodi interi invece che su blocchi specifici (lock contention), che degrada le performance.

Catchare Exception o Throwable generico invece dell'eccezione specifica, mascherando errori imprevisti di sistema.

Snippet e comandi

// Esempio try-with-resources
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    br.readLine();
} catch (IOException e) {
    e.printStackTrace();
}

// Stream API: filtrare e mappare una lista
List<String> nomi = List.of("Anna", "Marco", "Luca");
List<String> filtrati = nomi.stream()
    .filter(n -> n.startsWith("M"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// Singleton pattern thread-safe (Double-Checked Locking)
public class Singleton {
    private static volatile Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Da ripassare

[ ] Internals del Garbage Collector (G1GC vs ZGC).

[ ] Meccanismo dei ClassLoader in Java.

[ ] CompletableFuture e gestione asincrona.

[ ] Funzionamento interno di ThreadLocal.

Jarvis Interviews
Jarvis