Question
How can I generate a random int value within a specific range in Java?
The following approaches have problems related to correctness and integer overflow:
randomNum = minimum + (int)(Math.random() * maximum);
This is incorrect because randomNum can become larger than maximum.
Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum = minimum + i;
This is also incorrect because randomNum can become smaller than minimum.
What is the correct way to generate a random integer between minimum and maximum in Java?
Short Answer
By the end of this page, you will understand how to generate random integers in Java safely and correctly for both inclusive and exclusive ranges. You will also learn why some common formulas fail, how Random.nextInt(bound) works, and when to use Random, ThreadLocalRandom, or Math.random().
Concept
Generating a random integer in a range means producing a whole number between two limits, such as from 5 to 10.
The key idea is:
- Find the size of the range
- Generate a random offset inside that range
- Shift that offset by the minimum value
For example, if the range is 5 to 10 inclusive, the possible values are:
5678910
That is 6 values total, so the range size is:
maximum - minimum + 1
Then you generate a random number from 0 up to rangeSize - 1, and add minimum.
In Java, the safest standard approach is usually:
int randomNum = minimum + random.nextInt(maximum - minimum + 1);
This works because nextInt(bound) returns a value from 0 inclusive to bound exclusive.
So if bound is 6, the result is one of:
012345
Adding minimum shifts that to the desired range.
This matters in real programming because random values are used everywhere:
- game logic
- simulations
- test data generation
- sampling
- temporary codes
- choosing random items from collections
If the formula is wrong, your program may:
- generate values outside the expected range
- skip some values
- bias the distribution
- fail near integer limits
So this is not just about syntax. It is about correctness and reliability.
Mental Model
Think of a random number in a range like picking a seat number in a row.
If seats go from 20 to 25, you do not directly guess a number from the whole world of integers. Instead:
- Count how many seats exist
- Pick a random position starting from
0 - Move that many seats forward from seat
20
So:
- seat range:
20to25 - total seats:
6 - random offset:
0to5 - final seat:
20 + offset
That is exactly how random integer range formulas work.
The mistake beginners often make is mixing up:
- the largest allowed value
- the size of the range
These are not the same thing.
Syntax and Examples
Basic inclusive range with Random
import java.util.Random;
Random random = new Random();
int minimum = 5;
int maximum = 10;
int randomNum = minimum + random.nextInt(maximum - minimum + 1);
System.out.println(randomNum);
This returns a value from 5 to 10, including both ends.
Why this works
random.nextInt(maximum - minimum + 1)
If minimum = 5 and maximum = 10, then:
maximum - minimum + 1 = 6
So nextInt(6) returns one of:
0, 1, 2, 3, 4, 5
Then adding minimum gives:
5, 6, 7, 8, 9, 10
Using ThreadLocalRandom in modern Java
import java.util.concurrent.ThreadLocalRandom;
int minimum = 5;
int maximum = 10;
int randomNum = ThreadLocalRandom.current().nextInt(minimum, maximum + 1);
System.out.println(randomNum);
This is often cleaner. The second argument is exclusive, so maximum + 1 makes the upper limit inclusive.
Exclusive upper bound example
If you want values from 5 up to but not including 10:
int randomNum = ThreadLocalRandom.current().nextInt(5, 10);
Possible values are:
56789
Using Math.random() correctly
int minimum = 5;
int maximum = 10;
int randomNum = minimum + (int)(Math.random() * (maximum - minimum + 1));
System.out.println(randomNum);
This can work, but Random or ThreadLocalRandom is usually clearer and preferred in real code.
Important validation
Always ensure:
minimum <= maximum
For example:
if (minimum > maximum) {
throw new IllegalArgumentException("minimum must be <= maximum");
}
Step by Step Execution
Consider this code:
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random random = new Random();
int minimum = 3;
int maximum = 7;
int result = minimum + random.nextInt(maximum - minimum + 1);
System.out.println(result);
}
}
Step 1: Calculate the range size
maximum - minimum + 1
Substitute values:
7 - 3 + 1 = 5
So we need a random number from a set of 5 possible offsets.
Step 2: Generate the offset
random.nextInt(5)
This may return any of:
0, 1, 2, 3, 4
Suppose it returns 2.
Step 3: Shift by the minimum
result = 3 + 2;
So:
result = 5
Step 4: Check the possible outcomes
If the offset is:
0→ result is31→ result is42→ result is53→ result is64→ result is7
That exactly matches the desired inclusive range.
Why the broken % n version fails
int i = rn.nextInt() % n;
rn.nextInt() may be negative. In Java, % keeps the sign of the left operand, so i can be negative.
Example:
rn.nextInt() = -8
n = 5
-8 % 5 = -3
Then:
randomNum = minimum + (-3)
This can go below minimum.
Why the Math.random() * maximum version fails
minimum + (int)(Math.random() * maximum)
This uses maximum as if it were the range size, but it is not.
If:
minimum = 5maximum = 10
Then (int)(Math.random() * 10) can be from 0 to 9, and adding 5 gives 5 to 14.
That clearly exceeds maximum.
Real World Use Cases
Picking a random item ID for testing
When generating sample user IDs, order numbers, or ticket numbers, you often need a random integer in a valid numeric range.
Game development
Games use random ranges for:
- dice rolls
- enemy damage
- loot drops
- random spawn coordinates
Example:
int damage = ThreadLocalRandom.current().nextInt(10, 21);
This produces damage from 10 to 20 inclusive.
Simulations
In simulations such as queues, traffic, or load testing, random integers help model variable behavior.
Picking a random array index
String[] names = {"Ana", "Ben", "Cara"};
int index = ThreadLocalRandom.current().nextInt(0, names.length);
System.out.println(names[index]);
This is one of the most common real uses of ranged random integers.
Temporary codes or tokens
For simple non-secure uses such as demo verification codes:
int code = ThreadLocalRandom.current().nextInt(100000, 1000000);
This produces a 6-digit number.
For real security-sensitive tokens, use SecureRandom instead.
Real Codebase Usage
In real projects, developers usually wrap random range logic in a helper method instead of repeating formulas everywhere.
Helper method pattern
import java.util.concurrent.ThreadLocalRandom;
public static int randomInRange(int min, int max) {
if (min > max) {
throw new IllegalArgumentException("min must be <= max");
}
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
This improves readability and reduces mistakes.
Guard clause for validation
A common pattern is checking inputs early:
if (min > max) {
throw new IllegalArgumentException("Invalid range");
}
This prevents hidden bugs later.
Configuration-driven ranges
Applications often read limits from config files or environment variables:
int minRetries = 1;
int maxRetries = 3;
int retryDelay = ThreadLocalRandom.current().nextInt(minRetries, maxRetries + 1);
Test data generation
Developers often create random but valid values for automated tests:
int age = ThreadLocalRandom.current().nextInt(18, 66);
Error handling and boundary safety
When ranges might be near integer limits, developers are careful with max + 1 because it can overflow if max == Integer.MAX_VALUE.
In such cases, use a different strategy or a wider type like long when appropriate.
Multi-threaded applications
In concurrent code, ThreadLocalRandom is commonly preferred over sharing a single Random instance because it performs better and is designed for threaded use.
Common Mistakes
1. Using maximum instead of range size
Broken code:
int randomNum = minimum + (int)(Math.random() * maximum);
Why it is wrong:
maximumis the upper value, not the number of possible values- this can create numbers above the allowed maximum
Correct version:
int randomNum = minimum + (int)(Math.random() * (maximum - minimum + 1));
2. Using % to limit random numbers
Broken code:
int i = random.nextInt() % n;
Why it is wrong:
- results can be negative
- distribution may be uneven
Correct version:
int i = random.nextInt(n);
3. Forgetting whether the upper bound is inclusive or exclusive
nextInt(bound) means:
- lower bound is
0inclusive - upper bound is
boundexclusive
So:
random.nextInt(5)
returns 0 to 4, not 0 to 5.
4. Not validating min and max
Broken code:
int result = min + random.nextInt(max - min + 1);
If min > max, this fails.
Safer code:
if (min > max) {
throw new IllegalArgumentException("min must be <= max");
}
5. Ignoring overflow near integer limits
This can be dangerous:
ThreadLocalRandom.current().nextInt(min, max + 1);
If max is Integer.MAX_VALUE, then max + 1 overflows.
6. Using random APIs for security-sensitive tasks
For passwords, reset tokens, or secure codes, do not use Random or Math.random().
Use:
import java.security.SecureRandom;
Comparisons
| Approach | Example | Range Style | Good Choice? | Notes |
|---|---|---|---|---|
Math.random() | min + (int)(Math.random() * (max - min + 1)) | Inclusive with manual formula | Sometimes | Works, but less explicit |
Random.nextInt(bound) | min + random.nextInt(max - min + 1) | Inclusive with manual shift | Yes | Classic and common |
ThreadLocalRandom.nextInt(min, maxExclusive) | ThreadLocalRandom.current().nextInt(min, max + 1) | Upper bound exclusive | Yes | Very convenient, common in modern Java |
SecureRandom | min + secureRandom.nextInt(max - min + 1) | Inclusive with manual shift | Yes, for security | Slower but appropriate for secure values |
Random vs ThreadLocalRandom
| Feature | Random | ThreadLocalRandom |
|---|---|---|
| Easy to use | Yes | Yes |
| Good for single-threaded code | Yes | Yes |
| Better in multi-threaded code | No | Yes |
| Need to create an instance | Yes | No |
| Direct ranged method with origin and bound | No | Yes |
Inclusive vs exclusive upper bound
| Formula | Result |
|---|---|
random.nextInt(5) | 0 to 4 |
min + random.nextInt(max - min + 1) | min to max |
ThreadLocalRandom.current().nextInt(min, max) | min to max - 1 |
ThreadLocalRandom.current().nextInt(min, max + 1) | min to max |
Cheat Sheet
// Inclusive range: [min, max]
int value = min + random.nextInt(max - min + 1);
// Inclusive range with ThreadLocalRandom
int value = ThreadLocalRandom.current().nextInt(min, max + 1);
// Exclusive upper bound: [min, max)
int value = ThreadLocalRandom.current().nextInt(min, max);
// Math.random() version for inclusive range
int value = min + (int)(Math.random() * (max - min + 1));
Rules to remember
nextInt(bound)returns0tobound - 1- To include
max, usemax - min + 1 - Do not use
%to force a random value into a range - Validate that
min <= max - Watch out for overflow when using
max + 1 - Use
SecureRandomfor security-sensitive values
Safe helper
public static int randomInRange(int min, int max) {
if (min > max) {
throw new IllegalArgumentException("min must be <= max");
}
return min + new Random().nextInt(max - min + 1);
}
Edge case
If max == Integer.MAX_VALUE, then:
max + 1
overflows for int. Be careful with inclusive formulas that add 1 to the maximum.
FAQ
How do I generate a random integer between two numbers in Java?
Use:
int value = min + random.nextInt(max - min + 1);
This gives a value from min to max inclusive.
Why does random.nextInt() % n give wrong results?
Because random.nextInt() can be negative, and % n can also be negative. It can also produce uneven distribution.
Is Math.random() okay for generating random integers?
Yes, if used correctly with the proper range formula. But Random or ThreadLocalRandom is usually clearer.
What is the easiest modern Java way to generate a number in a range?
ThreadLocalRandom.current().nextInt(min, max + 1)
This is very readable for inclusive ranges.
Is the upper bound included in nextInt(bound)?
No. The upper bound is exclusive.
random.nextInt(5)
returns 0 to 4.
What should I use for secure random numbers in Java?
Use SecureRandom for passwords, tokens, session secrets, or verification codes that must be hard to guess.
What happens if min is greater than max?
Your code should reject that input, usually by throwing IllegalArgumentException.
Can max + 1 overflow in Java?
Yes. If max is Integer.MAX_VALUE, adding 1 overflows for int. That edge case needs special handling.
Mini Project
Description
Build a small Java program that simulates rolling a custom die. The user chooses a minimum and maximum value, and the program generates a random integer in that inclusive range. This demonstrates correct range calculation, input validation, and repeated random generation.
Goal
Create a reusable method that returns a random integer between min and max inclusive, then use it to print several sample results.
Requirements
[
"Create a method that accepts min and max as parameters.",
"Validate that min is less than or equal to max.",
"Generate a random integer in the inclusive range.",
"Call the method multiple times and print the results.",
"Use standard Java random utilities rather than manual modulo logic."
]
Keep learning
Related questions
Add External JAR Files to an IntelliJ IDEA Java Project
Learn how to add external JAR dependencies to an IntelliJ IDEA Java project using module libraries, and when to use Maven or Gradle instead.
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Call a Method After a Delay in Android Java
Learn how to run Java code after a delay in Android using Handler.postDelayed, manage the main thread, and cancel callbacks safely.