- 1 1. Cosa Imparerai in Questo Articolo
- 1.1 1.1 Capirai i Principali Metodi per Generare Numeri Casuali in Java
- 1.2 1.2 Capirai le Regole di Intervallo e le Idee Sbagliate Comuni
- 1.3 1.3 Imparerai la Differenza tra Riproducibilità e Rischio
- 1.4 1.4 Sarai in Grado di Scegliere “Casualità Sicura” vs. “Casualità Pericolosa”
- 1.5 1.5 Anche i Principianti Saranno in Grado di Spiegare “Perché Questo è il Modo Giusto”
- 2 2. Cosa Significano i “Numeri Casuali” in Java
- 2.1 2.1 “Random” Non Significa “Perfettamente Casuale”
- 2.2 2.2 Cos’è un Generatore di Numeri Pseudocasuali (PRNG)?
- 2.3 2.3 Quando la “Casualità Riproducibile” è Utile
- 2.4 2.4 Quando la Casualità NON Deve Essere Riproducibile
- 2.5 2.5 Cos’è una “Distribuzione Uniforme”? (Le Basi del Bias)
- 2.6 2.6 Esempi Comuni per Principianti di “Casualità Distorta”
- 3 3. Iniziare Rapidamente con Math.random()
- 4 4. Comprendere la classe principale java.util.Random
- 5 5. Controllare intervallo e riproducibilità con Random
- 6 6. Perché Random non è adatto per la sicurezza
- 7 7. Utilizzare SecureRandom per la casualità critica per la sicurezza
- 8 8. API Random moderne: ThreadLocalRandom e RandomGenerator
- 9 9. Riepilogo: Scegliere l’API Random Giusta in Java
1. Cosa Imparerai in Questo Articolo
When you try to work with “random numbers” in Java, you’ll quickly run into multiple options such as Math.random(), Random, and SecureRandom.
Many people end up thinking, “Which one am I supposed to use?”
In this section, we’ll start with the bottom line and clarify what you will be able to do by reading this article to the end. By understanding the big picture before diving into detailed mechanisms and code, the later sections will become much easier to follow.
1.1 Capirai i Principali Metodi per Generare Numeri Casuali in Java
This article explains the major ways to generate random numbers in Java step by step.
Specifically, you’ll learn:
- A simple method you can use immediately → Un metodo semplice che puoi usare subito
- A method that allows more programmatic control → Un metodo che consente un maggiore controllo programmatico
- A method for situations where security matters → Un metodo per situazioni in cui la sicurezza è importante
We’ll organize everything by use case so it’s easy to choose the right approach.
That means this article works for both:
- Beginners who want to try sample code → Principianti che vogliono provare il codice di esempio
- People who want to move beyond “it runs, so it’s fine” → Persone che vogliono andare oltre “funziona, quindi è ok”
The structure is designed to support both types of readers.
1.2 Capirai le Regole di Intervallo e le Idee Sbagliate Comuni
One of the biggest stumbling blocks when working with random numbers is range selection.
For example:
- You want a random number from 0 to 9 → Vuoi un numero casuale da 0 a 9
- You want to simulate a die roll from 1 to 6 → Vuoi simulare il lancio di un dado da 1 a 6
- You want random numbers that include negative values → Vuoi numeri casuali che includano valori negativi
In these cases, questions like the following come up constantly:
- Is the upper bound included? → Il limite superiore è incluso?
- Is the lower bound always included? → Il limite inferiore è sempre incluso?
- Why am I not getting the values I expected? → Perché non ottengo i valori che mi aspettavo?
This article explains it in a beginner-friendly flow:
“Why does it happen?” → “How do you write it correctly?”
1.3 Imparerai la Differenza tra Riproducibilità e Rischio
Random numbers can have opposite requirements depending on the situation:
- You want different results every time → Vuoi risultati diversi ogni volta
- You want to reproduce the same results repeatedly → Vuoi riprodurre gli stessi risultati più volte
For example:
- For testing and debugging, you want to reproduce “the same random values” → Per test e debug, vuoi riprodurre “gli stessi valori casuali”
- For passwords and tokens, you need “unpredictable random values” → Per password e token, hai bisogno di “valori casuali imprevedibili”
If you use them without understanding this difference, you can run into issues such as:
- Unstable tests → Test instabili
- Security-dangerous implementations → Implementazioni pericolose per la sicurezza
This article clearly separates:
“Randomness that should be reproducible” vs. “Randomness that must not be reproducible”
1.4 Sarai in Grado di Scegliere “Casualità Sicura” vs. “Casualità Pericolosa”
Java provides multiple random-number options that may look similar, but their purposes are completely different.
- Randomness suitable for games and sample code → Casualità adatta per giochi e codice di esempio
- Randomness that is fine for business applications → Casualità adeguata per applicazioni aziendali
- Randomness that is absolutely required for security use cases → Casualità assolutamente necessaria per casi d’uso di sicurezza
If you use them without distinguishing the purpose, you’re likely to end up with:
- “It seems to work, but it’s actually dangerous” → “Sembra funzionare, ma è in realtà pericoloso”
- “Code that becomes a problem later” → “Codice che diventa un problema in seguito”
This article explains the decision criteria with reasons, in the form:
“For this use case, use this.”
1.5 Anche i Principianti Saranno in Grado di Spiegare “Perché Questo è il Modo Giusto”
Instead of just listing code examples, we focus on the reasoning behind them, such as:
- Why this method is used → Perché questo metodo è usato
- Why this specific style is correct → Perché questo stile specifico è corretto
- Why other approaches are not suitable → Perché altri approcci non sono adatti
We emphasize the background and way of thinking.
So this is useful for people who want to:
- Understand and use it (not just memorize) → Capire e usarlo (non solo memorizzare)
- Reach a level where they can explain it to others → Raggiungere un livello in cui possono spiegarlo ad altri
as well.
2. Cosa Significano i “Numeri Casuali” in Java
Before generating random numbers in Java, this section organizes the core fundamentals you must know.
If you skip this and only copy code, you will almost certainly get confused later.
2.1 “Random” Non Significa “Perfettamente Casuale”
Un’idea sbagliata comune tra i principianti è questa:
I numeri casuali generati in Java non sono “perfettamente casuali”.
La maggior parte dei valori casuali usati in Java è più accuratamente descritta come:
- Numeri calcolati secondo regole fisse (un algoritmo)
- Sembrano casuali, ma internamente seguono uno schema
Questo tipo di casualità è chiamato numero pseudocasuale (output PRNG).
2.2 Cos’è un Generatore di Numeri Pseudocasuali (PRNG)?
Un generatore di numeri pseudocasuali è un meccanismo che:
- Parte da un valore iniziale (un seed)
- Ripete calcoli matematici
- Produce una sequenza che sembra casuale
I vantaggi principali includono:
- Generazione veloce
- Lo stesso seed riproduce la stessa sequenza casuale
- Facile da gestire sui computer
D’altra parte, gli svantaggi includono:
- Prevedibile se l’algoritmo è noto
- Potrebbe non essere adatto per casi d’uso di sicurezza
2.3 Quando la “Casualità Riproducibile” è Utile
A prima vista, potresti pensare:
Se gli stessi valori casuali appaiono, non è forse non casuale e quindi sbagliato?
Ma nella pratica, la casualità riproducibile è estremamente importante.
Ad esempio:
- Vuoi verificare gli stessi risultati ogni volta nel codice di test
- Vuoi riprodurre una segnalazione di bug
- Vuoi confrontare i risultati di simulazioni
In queste situazioni, è molto più pratico avere:
- Gli stessi valori casuali ad ogni esecuzione
- piuttosto che risultati che cambiano ogni volta
Molte classi Java per numeri casuali sono progettate tenendo conto di questa riproducibilità.
2.4 Quando la Casualità NON Deve Essere Riproducibile
D’altra parte, alcuni valori casuali non devono mai essere riproducibili.
Esempi tipici includono:
- Generazione di password
- Token di autenticazione
- ID di sessione
- Chiavi monouso
Se questi valori sono:
- Prevedibili
- Riproducibili
ciò da solo può portare a un grave incidente di sicurezza.
Ecco perché Java fornisce
generatori casuali focalizzati sulla sicurezza
separati dai normali generatori pseudocasuali.
Se implementi senza comprendere questa differenza, potresti facilmente finire con:
- Codice che “funziona” ma è pericoloso
- Codice che diventa un problema in revisioni o audit
Quindi assicurati di comprendere questo punto.
2.5 Cos’è una “Distribuzione Uniforme”? (Le Basi del Bias)
Un termine che appare spesso nelle discussioni sui numeri casuali è distribuzione uniforme.
Una distribuzione uniforme significa:
- Ogni valore appare con la stessa probabilità
Ad esempio:
- Un dado dove 1–6 sono ugualmente probabili
- Le cifre da 0 a 9 appaiono uniformemente
Quello stato è una distribuzione uniforme.
Le API casuali di Java sono generalmente progettate assumendo una distribuzione uniforme.
2.6 Esempi Comuni per Principianti di “Casualità Distorta”
Quando regoli manualmente i numeri casuali, puoi introdurre accidentalmente bias.
Esempi comuni includono:
- Forzare un intervallo usando
%(l’operatore modulo) - Castare
doubleaintnel punto sbagliato - Non comprendere se i limiti sono inclusivi
Questi sono insidiosi perché il codice continua a funzionare, il che rende l’errore
difficile da notare.
Le sezioni successive spiegheranno, con esempi concreti:
- Perché si verifica il bias
- Come scriverlo correttamente
così potrai evitare queste insidie.
3. Iniziare Rapidamente con Math.random()
Da qui, vedremo modi concreti per generare numeri casuali in Java.
Il primo metodo è Math.random(), il più semplice e il più comunemente incontrato dai principianti.
3.1 Cos’è Math.random()?
Math.random() è un metodo statico fornito da Java che restituisce un valore double casuale maggiore o uguale a 0.0 e minore di 1.0.
double value = Math.random();
Quando esegui questo codice, il valore restituito è:
- maggiore o uguale a 0.0
- minore di 1.0
In altre parole, 1.0 non è mai incluso.
3.2 Perché Math.random() è Così Facile da Usare
Il più grande vantaggio di Math.random() è che
non richiede assolutamente alcuna configurazione.
- Nessuna istanziazione di classe
- Nessuna dichiarazione di import
- Utilizzabile in una singola riga
Per questo, è molto comodo per:
- Esempi di apprendimento
- Demo semplici
- Verificare rapidamente il flusso del programma
in tali situazioni.
3.3 Generare numeri interi casuali con Math.random()
Nei programmi reali, spesso si desiderano numeri interi casuali
piuttosto che valori double.
3.3.1 Generare un numero casuale da 0 a 9
int value = (int)(Math.random() * 10);
I valori prodotti da questo codice sono:
- 0 o maggiore
- 9 o minore
Ecco perché:
Math.random()restituisce valori da 0.0 a 0.999…- Moltiplicando per 10 si ottiene da 0.0 a 9.999…
- Il cast a
inttronca la parte decimale
3.4 Un errore comune nella generazione da 1 a 10
Un errore molto comune per i principianti è dove spostare il valore di partenza.
int value = (int)(Math.random() * 10) + 1;
Questo produce numeri casuali che sono:
- maggiori o uguali a 1
- minori o uguali a 10
Se sbagli l’ordine e scrivi invece questo:
// Common mistake
int value = (int)Math.random() * 10 + 1;
Questo codice produce:
(int)Math.random()è sempre 0- Il risultato diventa sempre 1
Avvolgi sempre il cast tra parentesi — questo è un punto critico.
3.5 Vantaggi e limitazioni di Math.random()
Vantaggi
- Estremamente semplice
- Basso costo di apprendimento
- Sufficiente per casi d’uso piccoli e semplici
Limitazioni
- Nessuna riproducibilità (nessun controllo del seed)
- Nessun controllo interno
- Non adatto per casi d’uso di sicurezza
- Manca di flessibilità per scenari complessi
In particolare, se hai bisogno di:
- Gli stessi valori casuali nei test
- Controllo fine sul comportamento
allora Math.random() non sarà sufficiente.
3.6 Quando dovresti usare Math.random()
Math.random() è più adatto per:
- Apprendimento Java nelle fasi iniziali
- Codice di spiegazione degli algoritmi
- Esempi di verifica semplici
D’altra parte, per:
- Applicazioni aziendali
- Codice di test
- Logica legata alla sicurezza
dovresti scegliere un generatore di numeri casuali più appropriato.
4. Comprendere la classe principale java.util.Random
Ora passiamo a un passo oltre Math.random() e guardiamo
la classe java.util.Random.
Random è una classe fondamentale usata da molti anni in Java. Appare quando si desidera
“un controllo adeguato sui numeri casuali”.
4.1 Cos’è la classe Random?
Random è una classe per generare numeri pseudocasuali.
La si utilizza creando un’istanza così:
import java.util.Random;
Random random = new Random();
int value = random.nextInt();
La più grande differenza rispetto a Math.random() è che
il generatore di numeri casuali è trattato come un oggetto.
Questo ti permette di:
- Riutilizzare lo stesso generatore
- Mantenere il comportamento coerente
- Gestire esplicitamente la casualità nel tuo design
cosa non è possibile con Math.random().
4.2 Tipi di valori casuali che puoi generare con Random
La classe Random fornisce metodi adattati a diversi casi d’uso.
Esempi comuni includono:
nextInt(): un valoreintcasualenextInt(bound): unintda 0 (inclusivo) a bound (esclusivo)nextLong(): un valorelongcasualenextDouble(): undoubleda 0.0 (inclusivo) a 1.0 (esclusivo)nextBoolean():trueofalse
Scegliendo il metodo giusto, puoi generare valori casuali
naturalmente adatti a ciascun tipo di dato.
5. Controllare intervallo e riproducibilità con Random
Uno dei maggiori vantaggi dell’uso di java.util.Random è
il controllo esplicito su intervalli e riproducibilità.
5.1 Generare valori entro un intervallo specifico
Il metodo più comunemente usato è nextInt(bound).
Random random = new Random();
int value = random.nextInt(10);
Questo codice produce valori che sono:
- maggiori o uguali a 0
- minori di 10
Quindi l’intervallo di risultato è da 0 a 9.
5.2 Spostare l’intervallo (ad es., da 1 a 10)
Per spostare l’intervallo, basta aggiungere un offset:
int value = random.nextInt(10) + 1;
Questo produce valori da:
- 1 (inclusivo)
- 10 (inclusivo)
Questo schema:
random.nextInt(range) + start
è il modo standard per generare valori interi casuali all’interno di un intervallo in Java.
5.3 Generare Numeri Casuali con Intervalli Negativi
È anche possibile generare intervalli che includono valori negativi.
Ad esempio, per generare valori da -5 a 5:
int value = random.nextInt(11) - 5;
Spiegazione:
nextInt(11)→ da 0 a 10- Sottrai 5 → da -5 a 5
Questo approccio funziona in modo coerente indipendentemente dal segno dell’intervallo.
5.4 Riproducibilità con i Seed
Un’altra caratteristica chiave di Random è il controllo del seed.
Se specifichi un seed, la sequenza casuale diventa riproducibile:
Random random = new Random(12345);
int value1 = random.nextInt();
int value2 = random.nextInt();
Finché viene usato lo stesso valore di seed:
- Viene generata la stessa sequenza di valori casuali
Questo è estremamente utile per:
- Test unitari
- Confronti di simulazioni
- Debug di bug difficili
Al contrario, Math.random() non consente il controllo esplicito del seed.
6. Perché Random non è adatto per la sicurezza
A questo punto, potresti pensare:
Random può generare valori imprevedibili, quindi perché non è adatto per la sicurezza?
Questo è un fraintendimento molto comune.
6.1 La prevedibilità è il problema principale
java.util.Random utilizza un algoritmo deterministico.
Ciò significa:
- Se l’algoritmo è noto
- Se vengono osservati sufficienti valori di output
allora i valori futuri possono essere previsti.
Per giochi o simulazioni, questo non è un problema.
Per la sicurezza, è un difetto critico.
6.2 Esempi concreti di utilizzo pericoloso
Usare Random per quanto segue è pericoloso:
- Generazione di password
- Chiavi API
- Identificatori di sessione
- Token di autenticazione
Anche se i valori “sembrano casuali”, non sono crittograficamente sicuri.
6.3 La differenza chiave tra “aspetto casuale” e “sicuro”
La distinzione critica è la seguente:
- Random : veloce, riproducibile, prevedibile in teoria
- Secure random : imprevedibile, resistente all’analisi
La casualità orientata alla sicurezza deve essere progettata assumendo che:
- L’attaccante conosca l’algoritmo
- L’attaccante possa osservare gli output
Random non soddisfa questo requisito.
Ecco perché Java fornisce una classe separata specificamente per i casi d’uso di sicurezza.
7. Utilizzare SecureRandom per la casualità critica per la sicurezza
Quando la casualità deve essere imprevedibile e resistente agli attacchi,
Java fornisce java.security.SecureRandom.
Questa classe è progettata specificamente per casi d’uso sensibili alla sicurezza.
7.1 Cosa rende SecureRandom diverso?
SecureRandom differisce da Random nei suoi obiettivi di progettazione.
- Utilizza algoritmi crittograficamente robusti
- Preleva entropia da più fonti di sistema
- Progettato per essere imprevedibile anche se gli output sono osservati
A differenza di Random, lo stato interno di SecureRandom non è praticamente reversibile.
7.2 Uso base di SecureRandom
L’uso è simile a Random, ma l’intento è molto diverso.
import java.security.SecureRandom;
SecureRandom secureRandom = new SecureRandom();
int value = secureRandom.nextInt(10);
Questo produce valori da:
- 0 (inclusivo)
- 10 (esclusivo)
L’API è intenzionalmente simile in modo da poter sostituire Random quando necessario.
7.3 Quando è necessario usare SecureRandom
Dovresti usare SecureRandom per:
- Generazione di password
- ID di sessione
- Token di autenticazione
- Chiavi crittografiche
In questi scenari, usare Random non è “leggermente rischioso” — è scorretto.
Il costo prestazionale di SecureRandom è intenzionale e accettabile per la sicurezza.
8. API Random moderne: ThreadLocalRandom e RandomGenerator
Le versioni recenti di Java forniscono API random più avanzate per affrontare problemi di prestazioni e di progettazione.
8.1 ThreadLocalRandom: Casualità per il Multithreading
ThreadLocalRandom è ottimizzato per ambienti multithread.
Invece di condividere un’unica istanza di Random, ogni thread utilizza il proprio generatore.
int value = java.util.concurrent.ThreadLocalRandom.current().nextInt(1, 11);
Questo genera valori da 1 (inclusivo) a 11 (esclusivo).
I vantaggi includono:
- Nessuna contesa tra i thread
- Migliore prestazioni in presenza di concorrenza
- API basate su intervalli puliti
Per l’elaborazione parallela, questo è solitamente preferibile a Random.
8.2 RandomGenerator: Un’interfaccia unificata (Java 17+)
RandomGenerator è un’interfaccia introdotta per unificare la generazione di numeri casuali.
Consente:
- Cambiare facilmente gli algoritmi
- Scrivere codice indipendente dall’implementazione
- Progettazione più a prova di futuro
import java.util.random.RandomGenerator; RandomGenerator generator = RandomGenerator.getDefault(); int value = generator.nextInt(10);
Questo approccio è consigliato per codebase Java moderne.
9. Riepilogo: Scegliere l’API Random Giusta in Java
Java fornisce diverse API per i numeri casuali perché
“casualità” ha significati diversi a seconda del contesto.
9.1 Guida Rapida alla Decisione
Math.random(): apprendimento, demo sempliciRandom: test, simulazioni, comportamento riproducibileThreadLocalRandom: applicazioni multithreadRandomGenerator: design moderno e flessibileSecureRandom: password, token, sicurezza
Scegliere quella sbagliata potrebbe non causare errori immediati,
ma può creare problemi seri in seguito.
9.2 Il Principio Chiave da Ricordare
Il punto più importante è questo:
La casualità è una decisione di progettazione, non solo una chiamata di funzione.
Capendo l’intento dietro ogni API, puoi scrivere codice Java che è:
- Corretto
- Manutenibile
- Sicuro
E adatto per applicazioni reali.

