Data structures & algorithms · Stage 0 foundations
Variables, data types and I/O
A variable is a labelled box in memory. This page fills a box, overwrites one, swaps two numbers through a third — and then shows the three places where the box hands you a wrong answer without saying a word.
Fill the memory table yourself →01 The idea
A named box, and what fits inside it
Every value your program works with has to live somewhere. A variable is a name for one place in memory — a box — and everything you do with data comes down to three moves: put a value in a box, copy a value out of a box, or write over what a box already holds. The name is there for you. The machine only cares about the address.
The type is the part students skim, and it is the part that bites. int, double, char and boolean are not decorations. Each one fixes how many bits the box has and how those bits are read back. A four-byte int box cannot hold 3.5 and cannot count past 2,147,483,647, and when you ask it to, you do not get an error. You get a wrong number and a program that keeps running.
02 Memory trace
Swapping two numbers, box by box
Two variables: a holds 5, b holds 3, and you want them the other way round. Each row below is the state of memory after one line has run. A rose box is the box that line just wrote to. A dot means the box does not exist yet, a question mark means it exists but nothing has been written into it. Follow the 5 — it is the value that nearly gets lost.
Two facts in that trace do all the teaching. First, the temp = a row copies: once it has run the number 5 sits in two independent boxes, and changing one of them does not touch the other. Second, the a = b row destroys: the moment it runs, the 5 that was in a is gone from memory and nothing remembers it. The temp variable exists because those two facts collide — you have to save the value before the write that wipes it. Every "why do I need a third variable" question is that one sentence. Drop temp and the program still runs, still reports no error, and leaves both boxes holding 3.
03 Code and types
The same swap, read from input and printed back
Here is the trace as a whole program, with the two numbers coming from the keyboard instead of being written into the source. The values are the same 5 and 3, so you can lay this against the trace line by line.
Scanner sc = new Scanner(System.in);int a = sc.nextInt(); // you type 5int b = sc.nextInt(); // you type 3int temp; // declared, no value yettemp = a; // copy the 5 out of aa = b; // a is overwritten, the 5 is goneb = temp; // the saved copy lands in bSystem.out.printf("a=%d b=%d%n", a, b); // a=3 b=5
Declaration and initialisation are two separate events. Line 4 makes the box and stops. Java refuses to compile a read of a local variable that was never written to, which turns a whole family of bugs into a compile error. C does not stop you — it hands back whatever bits were already lying at that address, so the same program gives a different answer on a different run.
temp = a copies; it does not create an alias. That is the only reason line 6 is safe. Line 6 destroys the 5 inside a, and the copy sitting in temp is what line 7 hands to b. Reverse lines 5 and 6 and the copy is made after the value is already gone.
nextInt() reads a number, not a line. It consumes the digits and leaves the newline you pressed sitting in the buffer. Call nextLine() straight after it and you get an empty string, because that leftover newline is the first thing it finds. Consume it with one extra nextLine() before you read real text. This is the single most common input bug in a placement test.
%d is a promise about the type. In printf, %d says a whole number goes here and %.2f says a decimal rounded to two places goes here. Formatting changes what is printed and never what is stored — printf("%.2f", 3.14159) shows 3.14 while the variable still holds every digit.
The seven types you will actually use
| Type | What it holds | Size | Watch out for |
|---|---|---|---|
| int | Whole numbers, −2,147,483,648 to 2,147,483,647 | 4 bytes | 7 / 2 is 3, and one past the top wraps to the bottom |
| long | Whole numbers up to 9,223,372,036,854,775,807 | 8 bytes | Big literals need the suffix: 10000000000L |
| float | Decimals, about 7 significant digits | 4 bytes | Needs the f suffix, and 7 digits runs out fast |
| double | Decimals, about 15 significant digits | 8 bytes | 0.1 + 0.2 is not 0.3 |
| char | One character, written 'A' | 2 bytes | Single quotes, and 'A' + 1 is the int 66 |
| boolean | Exactly true or false | 1 bit of information | You cannot assign 0 or 1 to it in Java |
| String | Text, written "hello" | a reference | == compares identity, so use .equals |
Converting between types
Moving a value into a bigger box is safe, so the compiler does it silently. That is implicit conversion, also called widening: int → long → float → double. Write double d = 7; and d holds 7.0 with nothing lost. Moving a value into a smaller box can lose information, so the compiler refuses until you write the cast yourself. That is explicit conversion, or narrowing, and the cast is you signing for the loss.
05 Cheat sheet
The lines that get asked about
| You write | What happens | Result and gotcha |
|---|---|---|
| int a; | Declaration only — a 4-byte box, nothing in it | Java will not let you read it; C returns garbage |
| a = b; | Copies the value of b into a | The old a is gone; the two stay independent |
| 7 / 2 | int ÷ int is done as int division | 3 — truncates, never rounds |
| 7 % 2 | Remainder after that division | 1 — / and % together recover the whole answer |
| (int) 3.9 | Explicit narrowing, double to int | 3 — use Math.round if you meant 4 |
| 2147483647 + 1 | int arithmetic with no room left | -2147483648 — wraps silently, no error |
| 0.1 + 0.2 == 0.3 | Exact bit comparison of two doubles | false — compare with a tolerance |
| nextInt() then nextLine() | Reads the number, then the rest of that line | "" — the newline was still waiting |
06 Where & why
Which type do you actually pick
In a placement test, int and double cover almost everything you will write, and int is the sensible default. The choice still matters, because picking wrong does not give you an error message. It gives you a plausible wrong answer.
Reach for int when…
Use something else when…
| Situation | Better choice | Why |
|---|---|---|
| The count can pass two billion — milliseconds since 1970, file sizes, a sum of many large ints | long | int wraps at 2147483647 without a word. A long runs to about 9.2 quintillion. |
| Averages, ratios, distances, percentages | double | 7 / 2 in ints is 3. Anything measured needs a fractional part, and double gives about 15 digits. |
| Money | a long of paise, or BigDecimal | double cannot store 0.1 exactly, so rupee totals drift by a paisa and reconciliation fails. |
| A yes-or-no answer | boolean | Holding 0 and 1 in an int lets a bug store 7. A boolean has two values, so the compiler catches it. |
| Checking whether two pieces of text match | String with .equals | == asks whether they are the same object, not whether they read the same. Two identical strings from input can fail it. |
07 Interview questions
Say these out loud
The three trap questions come up in almost every first-round screen, and the interviewer is listening for why, not just the value.
What is a variable?
What is the difference between declaring and initialising a variable?
Swap two numbers. Why do you need a third variable?
Can you swap two ints without a temporary variable?
What does 7 / 2 give you, and why?
What is the range of an int, and what happens if you go past it?
Why is 0.1 + 0.2 not equal to 0.3?
float or double — which do you use?
What is the difference between implicit and explicit type conversion?
How do you read input, and what goes wrong with Scanner?
Why does == not work for comparing two Strings?
08 Practice problems
Write the boxes down first
For each one, write out the variables and their types before you write any code, then predict the output by hand and only then run it. The gap between your prediction and the output is the lesson.