Java / Basic / Lesson 2
Values, types, and numeric expressions
Choose representations that preserve the meaning of a value. Understand primitives, references, integer arithmetic, conversion, booleans, Unicode, and null.
On this page
Lesson goals
- Predict integer and floating-point calculations.
- Separate reference values from objects.
- Choose explicit conversion and validation boundaries.
Distinguish primitive values and references
Java variables have types that constrain their values and operations. int and long hold signed integers; double approximates real-number calculations; boolean holds true or false; char holds one UTF-16 code unit. A reference variable instead holds a reference to an object or null. Assigning a reference copies that value, not a duplicate of the object's contents.
Use domain meaning to choose a representation. A customer code containing leading zeros is usually text rather than a number. An exact monetary calculation needs a deliberate decimal design, such as BigDecimal with specified scale and rounding, rather than assuming double can represent every decimal fraction exactly. Type correctness is necessary but does not establish business correctness.
Follow operand types through division
Integer division discards the fractional part toward zero. Assigning the result to double afterward cannot recover what was already discarded. Promote an operand before division when a fractional result is required. The example contrasts 7 / 2 with 7 / 2.0 and uses remainder to check parity. Explain the expression's type before considering the destination variable.
Integer arithmetic can overflow without an exception in ordinary operators. A long destination does not rescue an int multiplication performed first; use a long operand or an exact operation when overflow must be detected. For a positive count calculation, also validate that inputs are nonnegative and that a zero denominator cannot occur. Numeric range and domain range are separate checks.
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(7 / 2);
System.out.println(7 / 2.0);
System.out.println(7 % 2);
}
}
3
3.5
1
Two int operands give 3. A double operand gives 3.5. The remainder after dividing seven by two is one.
Make conversions express a policy
Widening a numeric value is often implicit, while narrowing generally needs a cast and may lose information. Casting 3.9 to int gives 3 rather than rounding to the nearest integer. A parsing method converts text under its own rules and may reject it; a cast is not a text parser. Never use a narrowing cast merely to silence a compiler warning without understanding the lost range.
The exact-addition example uses Math.addExact for a small valid sum. This API throws ArithmeticException if its int result overflows, allowing an application to reject the calculation deliberately. The example does not trigger overflow, so its output is stable. When handling real user input, distinguish parse failure, arithmetic overflow, and a valid number outside the business range.
public class Main {
public static void main(String[] args) throws Exception {
int total = Math.addExact(40, 2);
int truncated = (int) 3.9;
System.out.println(total);
System.out.println(truncated);
}
}
42
3
The sum is within int range. The cast discards the fractional part; it does not call a rounding function.
Use booleans and null deliberately
Conditions require boolean expressions; Java does not interpret an arbitrary integer as true. && and
short-circuit, so a left-hand null check can guard a later dereference in the same expression. This does not replace a proper input contract: decide whether an absent name is allowed and how it differs from an empty or blank name.
Local variables must be definitely assigned before use. Fields receive default values, including zero or null, which can hide an incomplete object design. Wrapper types such as Integer can be null and automatically unboxing one then throws NullPointerException. Prefer primitives when absence has no meaning, and represent optional values explicitly at boundaries where it does.
Distinguish characters, code units, and bytes
A Java char is not an arbitrary full Unicode character. String indices use UTF-16 code units, and a supplementary code point occupies two units. Encoded bytes are another representation that requires a charset. An Arabic letter, an emoji, and a user-visible grapheme need not have the same count under all three measurements. State which unit an input length limit uses.
Keep literals, source encoding, and input decoding consistent. Compile this course with -encoding UTF-8 and use explicit UTF-8 when converting external bytes. A correct numeric type will not repair corrupted text, and a successful decoding step will not validate the business value. Treat representation and validation as related but separate responsibilities.
Common errors and fixes
Unexpected integer result
- Why it happens
- Integer division occurred before conversion to double.
- How to fix it
- Promote an operand before dividing.
- Prevent it next time
- Predict each subexpression type explicitly.
ArithmeticException
- Why it happens
- A zero integer divisor or exact-arithmetic overflow violated the operation contract.
- How to fix it
- Validate the divisor and range, and handle deliberate exact-operation failure.
- Prevent it next time
- Test zero, negative, and boundary values.
NullPointerException during unboxing
- Why it happens
- A wrapper reference was null when converted to a primitive.
- How to fix it
- Reject missing input or apply an explicitly defined default before unboxing.
- Prevent it next time
- Use primitives where absence is not meaningful.
Check your understanding
1. What do double x = 5 / 2 and double y = 5 / 2.0 contain?
Show worked solution
x contains 2.0 because int division completed first; y contains 2.5 because one operand was double. Changing the destination type alone does not change an already evaluated operation.
2. A product code is 00127. Should it be stored as int?
Show worked solution
Usually no: leading zeros belong to its identity and arithmetic is not meaningful. Use text with a validated format. If a separate numeric quantity is required, parse that separate field and check its domain range.
Key takeaways
- Expression types determine arithmetic behavior.
- A reference value can be null; an object is a different entity.
- Choose ranges, precision, and text units from requirements.