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.
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).
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.
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.
// 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;
}
}
[ ] Internals del Garbage Collector (G1GC vs ZGC).
[ ] Meccanismo dei ClassLoader in Java.
[ ] CompletableFuture e gestione asincrona.
[ ] Funzionamento interno di ThreadLocal.