The marks sheet that broke
Riya is building a marks sheet for her class: age, roll number, percentage, grade and pass/fail. She stores everything as int. The percentage 87.5 turns into an error, and the grade 'A' won't fit either. She asks Arjun Sir which type to use for what.
Sir, can't I just use int for everything? It's easier.
An int box only holds whole numbers, and only up to about 2.1 billion. 87.5 has a decimal part, 'A' is a character, and India's population needs a bigger box. Java gives you eight sizes and shapes of box, the primitive types.
Why not one giant box for everything?
Memory and speed. A college system might store crores of marks. Using 1 byte instead of 8 for each age saves a lot. Let's look inside each box, right down to the bits.
What are primitive data types?
A data type specifies the kind of values a variable can hold, the memory it needs and the operations allowed on it. Java has eight primitive data types, built into the language and not objects: four integer types (byte, short, int, long), two floating-point types (float, double), one character type (char) and one logical type (boolean). Their sizes are fixed by the language on every platform.
Primitives are Java's basic building blocks: whole numbers in four sizes, decimal numbers in two precisions, a single character, and true/false. They hold the value directly in the box, unlike objects (next lesson), where the box holds an arrow.
Words you'll meet in this lesson
42, 19.5, 'A', true.The eight primitives
| Type | Size | Range / values | Default | Example |
|---|---|---|---|---|
byte | 8 bits | −128 to 127 | 0 | byte age = 20; |
short | 16 bits | −32,768 to 32,767 | 0 | short year = 2026; |
int | 32 bits | about −2.1 billion to 2.1 billion (2,147,483,647) | 0 | int salary = 45_000; |
long | 64 bits | about ±9.2 × 1018 | 0L | long pop = 1_400_000_000L; |
float | 32 bits | ±3.4 × 1038, about 7 digits | 0.0f | float temp = 36.6f; |
double | 64 bits | ±1.8 × 10308, about 15–16 digits | 0.0 | double pct = 87.5; |
char | 16 bits | 0 to 65,535 (UTF-16 code unit) | '\u0000' | char grade = 'A'; |
boolean | not fixed by the spec | true or false | false | boolean passed = true; |
Exam tip: sizes are the same on every platform (that's Java's “portable” feature). Default choices: int for whole numbers, double for decimals. A plain number like 42 is an int literal and 19.5 is a double literal, so long values beyond int's range need L and float values need f. A boolean is not 0 or 1 in Java: you can't write if (1).
Four families, and how to write their values
Integers: byte, short, int, long
Whole numbers, positive or negative. Pick by range: int normally, long for big counts, IDs, timestamps in milliseconds or money in paise.
Floating point: float, double
Numbers with a decimal part, stored in binary scientific notation (IEEE 754). Very wide range, but approximate. Use double unless memory is very tight.
Character: char
One 16-bit Unicode code unit, written in single quotes: 'A', '₹', '\n'. Internally it's a number, so 'A' + 1 is 66.
Logical: boolean
Only true or false. The result of comparisons like marks >= 40, and the condition in every if and loop.
Writing literals
| Form | Example | Meaning |
|---|---|---|
| Decimal with underscores | 1_00_000 | One lakh. Underscores are only for readability (Java 7+). |
| Long suffix | 3_000_000_000L | A long literal. Use capital L, since small l looks like 1. |
| Float suffix | 36.6f | Without f, 36.6 is a double and won't fit in a float. |
| Hexadecimal / binary / octal | 0xFF · 0b1010 · 017 | 255 · 10 · 15 (a leading 0 means octal!) |
| Scientific notation | 1.5e3 | 1500.0 |
| char forms | 'A' · 'A' · 65 | All the same character A |
Choosing the right type: a checklist
Is it true/false?
Use
The JVM usually stores a boolean field in a byte, and boolean arrays use one byte per element, but the language never lets you treat it as a number.boolean:isPaid,hasDiscount,passed.Is it a single character?
Use
char: a grade, a gender code, a menu option. For words and sentences, useString(next lesson).'A'is stored as the number 65 in 16 bits:0000 0000 0100 0001.Is it a whole number?
Default to
Arithmetic is done in at least 32 bits anyway:int. If it could exceed about 2.1 billion (bank balances in paise, file sizes, timestamps in milliseconds, IDs in big systems), uselong.byte + byteproduces anint. byte and short mainly save memory in large arrays.Does it have a decimal part?
Use
A double stores a sign bit, 11 exponent bits and 52 fraction bits. Most decimal fractions, like 0.1, have no exact binary form, so tiny rounding errors appear.doublefor measurements: percentages, distances, temperatures.Is it money?
Don't use
₹0.10 + ₹0.20 as doubles gives 0.30000000000000004. In a bank, those tiny errors add up across millions of transactions.double. Store paise in along, or useBigDecimal(Module 10).
Inside the boxes: the bits behind each value
Left: the code and what it prints. Right: the actual bits in memory.
byte age = 100;fits easily: a byte holds −128 to 127.'A' + 1prints 66, because a char is stored as a number (65). Casting back gives 'B'.Integer.MAX_VALUEis 2,147,483,647, the largest int.- Adding 1 gives −2,147,483,648. Java doesn't stop you: the value wraps around.
0.1 + 0.2prints 0.30000000000000004. Decimals in double are approximate.- A comparison like
marks >= 40produces a boolean: true or false.
- 100 is stored as the 8 bits
0110 0100: 64 + 32 + 4. The leftmost bit is the sign. 'A'is the 16-bit Unicode number 65. In arithmetic, chars are promoted to int.- The largest int has a 0 sign bit and 31 ones: 2³¹ − 1.
- Adding 1 carries into the sign bit. In two's complement that pattern is the most negative int.
- A double has a sign, an exponent and a 52-bit fraction. 0.1 repeats forever in binary, so it's rounded.
- The sizes side by side: 8, 16, 16, 32, 32, 64 and 64 bits. boolean's size is left to the JVM.
Picking types in real systems
Wrong type choices are behind some famous software bugs. Here's how real systems choose.
Watch it with an example: when the box is too small
A video app counts views in an int. A shop adds prices in double. Both hit a surprise. Watch what happens to the bits, and the fix.
- The limit: an
inthas 32 bits. The first bit is the sign, so the largest value is 2,147,483,647 (about 214 crore). - Overflow: add 1 and the bits roll over to 1000…0, which means the most negative int. No error is shown; the views count silently becomes negative.
- Fix: use
long(64 bits) for counts that can grow big: views, transaction IDs, timestamps in milliseconds. - Fractions:
doublestores numbers in binary. 0.1 and 0.2 cannot be stored exactly, only very close values. - Surprise: the tiny errors add up, and Java prints 0.30000000000000004. Fine for distances or sensor readings, risky for money.
- Fix for money: count whole paise in a
long(or useBigDecimal, later). Integers are exact.
1. Money in banking and payments
Payment systems commonly store amounts as whole paise in a long, or use BigDecimal, so every rupee adds up exactly. Floating-point types are avoided for money.
2. Maps, GPS and sensors
Latitude, longitude, speed and temperature are measurements with natural tiny errors anyway, so double is the right choice. Ride-hailing and delivery apps calculate distances with doubles.
3. Timestamps and IDs
System.currentTimeMillis() returns a long: milliseconds since 1 January 1970 are far beyond int's range. Order IDs and user IDs in large systems are also usually long.
4. Images, files and network data
Raw data such as image pixels, PDF files and network packets is handled as byte arrays. A photo upload is millions of bytes, so the smallest type matters.
5. Indian languages and symbols
Because char is Unicode, Java handles Devanagari, Tamil, Bengali and the ₹ sign naturally. That's why Java apps serve users in many Indian languages.
Examples are simplified to show type choices. Each company's design varies.
Riya's marks sheet, with the right types
public class Main {
public static void main(String[] args) {
byte age = 20;
int rollNo = 2041;
long aadhaarLikeId = 9_876_543_210L;
double percentage = 87.5;
char grade = 'A';
boolean passed = percentage >= 40;
System.out.println("Age: " + age + ", Roll: " + rollNo);
System.out.println("ID: " + aadhaarLikeId);
System.out.println("Percentage: " + percentage + ", Grade: " + grade);
System.out.println("Passed: " + passed);
System.out.println("int max: " + Integer.MAX_VALUE);
}
}byte age = 20;Ages fit easily in a byte (−128 to 127).9_876_543_210LBigger than int's maximum, so it needslongand the L suffix. Underscores are just for reading.double percentage = 87.5;Decimal values default to double.char grade = 'A';Single quotes for one character. Double quotes would make a String.percentage >= 40A comparison: its result is a boolean, stored inpassed.
Six types in one frame, and an overflow
All these primitives live directly in main's stack frame: no arrows, no heap objects (except the strings we print).
Worked examples: real problems, solved and traced in memory
Choosing the right primitive type is a real design decision: too small and numbers overflow, decimals in double aren't exact, and char is secretly a number. Each program below shows one of these in action.
Pick a type for every field of a product
Problem statement
An online store keeps, for each product: number in stock, total units ever sold, price, rating, size letter and whether it's in stock. Pick the most suitable primitive type for each and print a product summary.
stock 42, sold 3,200,000,000 (all time), price 1499.00, rating 4.3, size 'M', in stock
Stock 42, sold 3200000000 Price 1499.0, rating 4.3, size M, available true
Approach
intfor small counts;longfor counts beyond 2.1 billion.doublefor price and rating (decimals).charfor one letter,booleanfor yes/no.
Solution: run it live
What happens in memory, step by step
Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.
Why money shouldn't be stored in double
Problem statement
A banking app adds 10 paise (0.10) to a balance three times and expects 0.30. With double it gets something slightly different, because binary fractions can't hold 0.1 exactly. Show the problem and the usual fix: count in paise with long.
0.10 added three times
double: 0.30000000000000004 (equals 0.3? false) paise: 30 = Rs 0.30
Approach
- Add 0.10 to a double three times and print it.
- Do the same in paise with a long.
- Compare both to the expected value.
Solution: run it live
What happens in memory, step by step
Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.
char is a number: the next seat letter
Problem statement
A theatre names rows A, B, C… A customer is in row 'C' and wants the row 2 behind. Since char stores a character code, you can add to it. Print the code and the new row.
row 'C', move 2 rows back
Row C has code 67 Two rows back: E
Approach
- Store the row as a
char. - Its numeric code:
(int) row. - Add 2 and cast back to
char.
Solution: run it live
What happens in memory, step by step
Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.
Check yourself
Quick revision
Lesson 2.2 in one screen
- 8 primitives: byte 8, short 16, int 32, long 64, float 32, double 64, char 16 (Unicode), boolean (true/false).
- Defaults: int for whole numbers, double for decimals.
Lfor long literals,ffor float. - Integer overflow wraps silently:
MAX_VALUE + 1 = MIN_VALUE. - int ÷ int drops the fraction;
%gives the remainder. - float/double are approximate:
0.1 + 0.2 ≠ 0.3. Never use them for money. - char is a number:
'A'= 65. boolean is never a number. - Primitives hold values directly (stack for locals); they are not objects.
Interview and viva questions
Why does Java have primitive types if it's object-oriented?
For speed and memory. A primitive is a plain value with no object overhead, so arithmetic is fast and arrays of numbers are compact. Wrapper classes (Integer, Double…) exist when you need an object version (Module 10).
Why is char 2 bytes in Java but 1 byte in C?
Java uses Unicode from the start, so a char holds a 16-bit UTF-16 code unit, enough for most of the world's scripts. Characters outside that range (some emoji, rare scripts) take two chars, called a surrogate pair.
What is the size of a boolean?
The language specification doesn't fix it. HotSpot typically uses one byte for boolean fields and array elements, and an int-sized slot for local variables. Only true and false are ever visible to your code.
Why is 0.1 + 0.2 not equal to 0.3?
double stores numbers in binary. 0.1 and 0.2 are repeating fractions in binary, so each is rounded to the nearest representable value. Their sum is slightly off: 0.30000000000000004. Compare doubles with a tolerance, and use BigDecimal or integer paise for money.
How do you detect integer overflow?
Use a bigger type (long), or Math.addExact, Math.multiplyExact and similar methods, which throw ArithmeticException on overflow instead of wrapping silently.
Practice problems
Pick the right primitive type, and see each type's limits and quirks. Every output is fixed. The last three are business tasks.
All eight types
Declare one variable of each primitive type and print them on one line.
(none)
10 300 70000 9000000000 2.5 3.14159 J true
Show solution and explanation
public class Main {
public static void main(String[] args) {
byte b = 10; short s = 300; int i = 70000; long l = 9000000000L;
float f = 2.5f; double d = 3.14159; char c = 'J'; boolean ok = true;
System.out.println(b + " " + s + " " + i + " " + l + " " + f + " " + d + " " + c + " " + ok);
}
}How it works: byte, short, int, long hold whole numbers of increasing size; float and double hold decimals; char one character; boolean true/false.
Type limits
Print the smallest and largest byte.
(none)
-128 to 127
Show solution and explanation
public class Main {
public static void main(String[] args) {
System.out.println(Byte.MIN_VALUE + " to " + Byte.MAX_VALUE);
}
}How it works: a byte is 8 bits, so it holds −128 to 127.
Character code
Print the numeric code of 'A' and of 'a'.
'A', 'a'
65 97
Show solution and explanation
public class Main {
public static void main(String[] args) {
System.out.println((int) 'A' + " " + (int) 'a');
}
}How it works: lowercase letters come 32 codes after uppercase ones.
Integer division vs double division
Print 7 / 2 and 7 / 2.0.
7, 2
3 3.5
Show solution and explanation
public class Main {
public static void main(String[] args) {
System.out.println(7 / 2);
System.out.println(7 / 2.0);
}
}How it works: if both operands are ints, the result is an int (the fraction is dropped).
byte overflow
Store 127 in a byte, add 1 with ++, and print it.
127
-128
Show solution and explanation
public class Main {
public static void main(String[] args) {
byte level = 127;
level++;
System.out.println(level);
}
}How it works: the value wraps around from 127 to −128.
Price in paise
Store a price of Rs 249.50 as paise in a long and print it back in rupees and paise.
249.50
Rs 249.50
Show solution and explanation
public class Main {
public static void main(String[] args) {
long paise = 24950;
System.out.println("Rs " + paise / 100 + "." + paise % 100);
}
}How it works: money in the smallest unit is exact; divide and take the remainder to display it.
In-stock flag
A product has 0 units. Store inStock as a boolean and print it, then print it for 15 units.
0, 15
In stock: false In stock: true
Show solution and explanation
public class Main {
public static void main(String[] args) {
int units = 0;
boolean inStock = units > 0;
System.out.println("In stock: " + inStock);
units = 15;
inStock = units > 0;
System.out.println("In stock: " + inStock);
}
}How it works: a comparison produces a boolean you can store and print.
Daily visitors over a year
A website gets 80 lakh visits a day. Print the yearly total using long.
8000000 × 365
Yearly visits: 2920000000
Show solution and explanation
public class Main {
public static void main(String[] args) {
long daily = 8_000_000;
System.out.println("Yearly visits: " + daily * 365);
}
}How it works: 2,920,000,000 is larger than an int can hold; long has room.
Real-world scenario questions (asked in company interviews)
Type choices look small, but they cause real money and data problems. Decide your answer first, then open the model answer.
The invoice total that's off by one paisa
An invoicing service stores prices as double. Finance reports that a few thousand invoices each month are off by ₹0.01 compared with the bank statement. Each line item looks correct. What's the likely cause, and how would you fix it?
The interviewer is checking: do you know that floating-point types are approximate, and the standard ways to handle money?
Show a strong answer
double stores values like 0.10 approximately in binary. When many items are added, multiplied by tax rates and rounded at different points, the tiny errors can push a total over a rounding boundary by one paisa.
- Store amounts as whole paise in a long, or use BigDecimal with an explicit rounding mode (for example
HALF_UP) and scale 2. - Decide and document where rounding happens (per line or per invoice), matching the finance/tax rules.
- Store the same exact type in the database (a DECIMAL column, not FLOAT).
- Add tests with known tricky values like 0.1 + 0.2.
Avoid: “Just round at the end with Math.round.” It hides some cases but doesn't make double exact.
Negative revenue in the sales report
After a big festival sale, the daily dashboard shows negative total revenue. The code adds up order amounts in paise into an int total. On normal days the numbers are fine. What happened?
The interviewer is checking: do you recognise integer overflow, and do you know how to prevent it?
Show a strong answer
An int can hold at most 2,147,483,647, which in paise is only about ₹2.15 crore. The sale pushed the total past that, so the value wrapped around to a negative number without any error.
- Use
longfor totals (up to about 9.2 × 1018 paise), or BigDecimal. - Use
Math.addExactwhere overflow must never pass silently; it throws an exception instead. - Check the database column and any reporting code for the same limit.
- Add a test with values near the limit, and alerting on impossible values like negative revenue.
Avoid saying: “Java would throw an error if the number was too big.” It doesn't for int and long arithmetic.
New users can't sign up
A fast-growing app suddenly fails to create new accounts. The logs show user IDs becoming negative. The database ID column is a 64-bit BIGINT, but the Java code reads IDs into an int userId. Why now, after years of working fine?
The interviewer is checking: do you understand type ranges across systems, and the need to keep Java and database types consistent?
Show a strong answer
The IDs only just crossed int's maximum of 2,147,483,647. Until then every ID fitted in an int. The next ID no longer fits; converting it to int keeps only the low 32 bits, which can produce a negative or wrong number.
- Change the Java type to
longeverywhere the ID flows: entities, APIs, caches and clients. - Check other services and mobile apps that consume the ID, since they may have the same limit.
- Rule of thumb: Java types should match the database column (BIGINT → long).
Avoid: “Reset the ID counter.” That risks duplicate IDs and doesn't fix the type mismatch.
The temperature alert that never fires
A vaccine fridge monitor calculates an average temperature as a double and raises an alert with if (avgTemp == 8.0). Testers saw the reading pass through 8 degrees, but no alert came. Why?
The interviewer is checking: do you know not to compare floating-point values with ==?
Show a strong answer
A calculated double is rarely exactly 8.0. It might be 7.999999999 or 8.000000001, so the == check is almost never true.
- For thresholds, use a range:
if (avgTemp >= 8.0), which also catches values that jump past 8. - When equality is really needed, compare with a tolerance:
Math.abs(a - b) < 0.0001. - Test with values just below, at and just above the limit.
Avoid: using == with float or double results of calculations.