Tag: java, jvm, spring, multithreading, collections, backend
Livello: intermedio
TL;DR: Schema rapido su architettura JVM, gestione della memoria, costrutti di concorrenza, collezioni fondamentali e framework Spring per sostenere colloqui tecnici backend.
La JVM gestisce memoria, garbage collection e traduzione del bytecode in codice macchina nativo.
Heap memory ospita tutti gli oggetti instanziati ed è condivisa tra i thread.
Stack memory conserva frame di metodi, variabili primitive e riferimenti locali specifici di ciascun thread.
String è immutabile; le modifiche creano nuovi oggetti a meno di usare StringBuilder o StringBuffer.
Il Garbage Collector individua oggetti non raggiungibili tramite algoritmi basati su analisi di raggiungibilità dalle GC Roots.
Il contratto equals e hashCode impone che oggetti uguali secondo equals debbano produrre lo stesso hash intero.
HashMap distribuisce le chiavi in bucket usando hashCode e gestisce le collisioni tramite linked list e alberi Red-Black.
L'astrazione di Spring IoC Container gestisce ciclo di vita e dipendenze dei bean tramite Dependency Injection.
Le annotazioni @Transactional sfruttano Spring AOP per intercettare chiamate pubbliche e gestire commit o rollback transazionali.
I thread pool creati tramite ExecutorService ottimizzano il riuso dei thread del sistema operativo evitando costosi overhead di creazione.
Q: Qual è la differenza sostanziale tra Heap e Stack in Java?R: Lo Stack alloca memoria veloce per l'esecuzione dei metodi e riferimenti locali del singolo thread; lo Heap conserva gli oggetti veri e propri ed è condiviso globalmente.
Q: Come funziona internamente una HashMap in Java 8+?R: Memorizza elementi in un array di bucket calcolando l'hash della chiave. In caso di collisioni multiple oltre una soglia, converte la lista concatenata in albero Red-Black per garantire ricerca in tempo logaritmico.
Q: Perché il rispetto del contratto tra equals() e hashCode() è cruciale?R: Se sovrascrivo equals senza allineare hashCode, collezioni come HashSet o HashMap non riescono a ritrovare elementi equivalenti perché finiscono in bucket errati.
Q: Come funziona il meccanismo di Dependency Injection in Spring?R: Delega la creazione e l'iniezione delle dipendenze al container IoC, che risolve i bean tramite annotazioni come @Autowired o iniezione via costruttore.
Q: Qual è la differenza tra fail-fast e fail-safe negli iteratori?R: Un iteratore fail-fast lancia subito ConcurrentModificationException se la collezione viene modificata durante l'iterazione; un iteratore fail-safe lavora su un clone della struttura dati.
Q: Cosa comporta dichiarare una variabile volatile?R: Garantisce che ogni lettura e scrittura avvenga direttamente nella memoria centrale anziché nelle cache locali dei singoli core della CPU, assicurando visibilità immediata tra thread.
Rompere il contratto equals/hashCode alterando il comportamento di lookup in strutture hash.
Usare la concatenazione operatore + su String dentro loop intensivi provocando allocazioni eccessive nello Heap.
Invocare un metodo annotato con @Transactional dall'interno della stessa classe bypassando il proxy AOP di Spring.
Dimenticare di gestire contesti concorrenti riutilizzando istanze SimpleDateFormat, non thread-safe rispetto a java.time.format.DateTimeFormatter.
Modificare una Collection standard durante un ciclo for-each senza passare dal metodo remove() dell'iteratore.
Catturare genericamente Throwable o sopprimere InterruptedException resettando impropriamente il flag di interruzione del thread.
// Implementazione corretta del contratto equals e hashCode
public record Utente(Long id, String email) {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Utente utente)) return false;
return Objects.equals(id, utente.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
Java
// Configurazione ThreadPool con ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<String> task = executor.submit(() -> {
return "Elaborazione completata";
});
String risultato = task.get();
executor.shutdown();
[ ] Garbage collector moderni: G1, ZGC e Shenandoah.
[ ] Differenza pratica tra interfacce funzionali Predicate, Function, Supplier e Consumer.
[ ] Meccanismi di locking ad alte prestazioni nel package java.util.concurrent.locks.
[ ] Propagazione delle transazioni in Spring: REQUIRED vs REQUIRES_NEW.
[x] Gerarchia delle eccezioni tra Checked e Unchecked.
[x] Principi SOLID applicati allo sviluppo ad oggetti.
Java Language and Virtual Machine Specifications
Effective Java (Joshua Bloch)
Documentazione ufficiale Spring Framework e Spring Boot