Unit 02 · lesson
Overflow and Precision Are Program Behavior
Types do more than decide what syntax compiles. Numeric representations have limits, and those limits can become visible program behavior.
Integers have a finite range
Java's int type uses 32 bits and has a finite minimum and maximum value.
Run:
void main() {
int value = Integer.MAX_VALUE;
IO.println(value);
value = value + 1;
IO.println(value);
}
The second value does not become a larger positive number. The representation wraps into the negative range.
That is integer overflow.
Nothing in the syntax announces, "This mathematical result no longer fits the chosen representation." The program can keep running with a value that destroys your business rule.
Bigger is not always enough
long provides a much larger integer range, but it is still finite.
The engineering question is not "Which type is biggest?" It is:
What values can this system legitimately encounter?
What operations can increase their magnitude?
What should happen when the valid range is exceeded?
For ordinary classroom counts, int is often fine. For timestamps, IDs, accumulated byte counts, or large financial/scientific calculations, representation deserves more deliberate thought.
Floating point is not exact decimal arithmetic
Predict:
void main() {
double total = 0.1 + 0.2;
IO.println(total);
}
You may see a value like:
0.30000000000000004
Binary floating-point cannot represent every decimal fraction exactly. That is not Java "forgetting" arithmetic. It is a consequence of representing a huge set of real-number approximations with finite binary patterns.
This matters when code compares calculated values.
Risky:
if (0.1 + 0.2 == 0.3) {
IO.println("equal");
}
Later we will use tolerances when comparing measured or calculated floating-point values.
Representation follows the domain
For a classroom robot telemetry system:
- motor rotations may be naturally fractional;
- event count is naturally integral;
- a device ID may look numeric but actually be text;
- money often needs decimal rules that should not be modeled casually with binary floating point.
The best type is the type whose behavior matches the domain closely enough for the program's requirements.
Boundary experiment
Run these in separate controlled tests:
int max = Integer.MAX_VALUE;
IO.println(max + 1);
int min = Integer.MIN_VALUE;
IO.println(min - 1);
double a = 0.1;
double b = 0.2;
IO.println(a + b);
For each, record:
- prediction;
- actual result;
- representation rule that explains it;
- one kind of application where this could matter.
Design a safer counter
Imagine a fictional sensor service that increments a reading counter continuously. You do not know whether an int will ever overflow during the service lifetime.
Do not immediately "fix" it with a random larger type. Write the questions you would need answered:
- maximum expected event rate;
- maximum continuous runtime;
- whether the counter resets;
- what the counter is used for;
- what failure behavior is acceptable.
Then choose a type based on those assumptions and record the assumptions with the decision.
That is software engineering: the representation is justified by system constraints, not chosen because one keyword feels safer.