1. Memory layout
Every computer has random-access memory (RAM). What is it, what properties does it have, and—most importantly—how does it help us?
Every program (including programs written in Java) is loaded into RAM before execution. RAM holds the program’s code (which the CPU executes) and the program’s data (which the program itself places into memory).
So, what is RAM and what is it like?
Imagine Excel 😎 A sheet in Excel consists of cells, and each cell has its unique identifier (A1, A2, ... B1, B2). Knowing a cell’s identifier, you can always write some value into it or read the value stored there. Computer memory is organized in a similar way.

The program and its data are stored in memory while it runs. All computer memory is represented as tiny cells—bytes. Each cell has its unique number—0, 1, 2, 3, ... (numbering starts at zero). Knowing a cell number, we can save some data into that cell—or take it from there. Some cells hold the program’s code—a set of CPU instructions; others hold the program’s data. The cell’s number is also called the cell address.
The CPU can execute instructions from the program loaded into memory. Almost all CPU instructions are something like: take data from some cells → do something with them → put the result into other cells.
By combining hundreds of simple instructions, we get complex and useful operations.
When a variable is declared in the program’s code, a chunk of as-yet unused memory is allocated for it. Typically, that is a few bytes. When declaring a variable, you must specify the type of information the program will store in it: numbers, text, or other data. Without knowing the type, it’s unclear how large a block of memory to allocate for the variable.
In the early days of computing, programs worked directly with memory cell numbers, but later, for the convenience of programmers, cells began to be given names. A variable’s unique name is primarily for the programmer’s convenience: at runtime the program would do just fine with numbers.
2. Variables in memory
In Java there are 4 main data types for storing integers: byte, short, int, and long.
| Type | Size, bytes | Name origin |
|---|---|---|
|
|
Byte, because it occupies one byte of memory |
|
|
Short for Short Integer |
|
|
Short for Integer |
|
|
Short for Long Integer |
There are also 2 floating-point types in Java — float and double:
| Type | Size, bytes | Name origin |
|---|---|---|
|
|
Short for Floating Point Number |
|
|
Short for Double Float |
Each time execution reaches a variable declaration, a small region of memory is allocated (the size depends on the variable’s type).
The address of a variable is considered to be the address of the first cell of the block of memory allocated for it.
Java programs are not allowed to access memory directly. All interaction with memory happens only through the Java Virtual Machine (JVM).
3. The String type in memory
The String type can store large amounts of data, so it’s not just a data type but a full-fledged object.
The actual String data (text) is placed into a special object for which memory is allocated, and the address of that object is then placed into a variable, for which memory is also allocated.

- The variable a of type int occupies 4 bytes and stores the value 1.
- The variable b of type int occupies 4 bytes and stores the value 10,555. The comma is not the fractional part of the number but a thousands separator. The fractional part is separated by a dot.
- The variable d of type double occupies 8 bytes and stores the value 13.001.
- The variable str of type String stores the value D12—the address of the first cell of the object containing the text.
The object of type String (which contains the text) is stored as a separate block of memory. The address of its first cell is stored in the variable str.
4. What happens when we assign
Another important thing is how assignment works. For example:
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
In this example, two cells are created in memory: one for a, one for b. When we write b = a;, the value (10) is copied, not the “box” itself. Changes to b do not affect a in any way.
Now the same, but with strings:
String s1 = "Hello";
String s2 = s1;
s2 = s2 + " World";
System.out.println(s1); // "Hello"
System.out.println(s2); // "Hello World"
Here both variables s1 and s2 refer to the same string "Hello" up until the change. But when we perform s2 = s2 + " World";, a new string "Hello World" is created for s2, while s1 still points to the old string "Hello".
5. Why indexing often starts at zero in programming
People are often surprised that in programming it’s customary to count from zero almost everywhere. The fact is, there are many situations in which it’s more convenient to start from zero (though there are also situations where it’s more convenient to start from 1).
Here’s an analogy. You’re standing in a long line at a store. The cashier says that all customers starting from the 20th should go to the second register. What numbers will they have? 20, 21, 22, 23, ... Makes sense. Relative to the 20th? 0, 1, 2, 3, ...
When we define a group as “index of the first element” + “count”, then inside the group the relative indices become +0, +1, +2, ...
It’s the same in programming. If your variable has been allocated 100 bytes of memory and you have X as the address of the first byte, then what will the addresses of all the bytes be? X+0, X+1, X+2, ..., X+99. There you have a group of bytes with indices 0, 1, 2, 99.
When we think in terms of a relative address inside some block of data, we naturally get numbering from zero. This is the first and most common reason to count from zero.
GO TO FULL VERSION