Source code, and why it is text
What a source file actually is, what an encoding is, and why your editor matters less than you think.
A source file is text. Not a document, not a project, not a special format — a sequence of characters, exactly like a note to yourself, that happens to follow rules strict enough for a machine to read.
That is worth proving rather than asserting. Here are the first thirty-two bytes of a Java file, printed as characters:
0000000 p u b l i c c l a s s H e l
0000020 l o { \n p u b l i cAnd the same thirty-two bytes as the numbers they actually are:
0000000 70 75 62 6c 69 63 20 63 6c 61 73 73 20 48 65 6c
0000016 6c 6f 20 7b 0a 20 20 20 20 70 75 62 6c 69 63 2070 is p. 20 is a space. 0a is the newline at the end of the first line, and the four 20s after it are the indentation — which is how you can tell, from the bytes alone, that this file uses spaces rather than a tab. The whole file is 111 bytes, and every one of them is something you could type.
What follows from that
Any editor works. Notepad, vim, IntelliJ — they all write the same bytes. An IDE gives you a great deal (the lesson on it says what), but none of it changes the file. This is why you can read a project on GitHub in a browser, and why a diff is a list of changed lines rather than a mysterious blob.
Whitespace is mostly for you. Java does not care about indentation; it cares about {, } and ;. Indentation exists so that a human can see the structure at a glance. Languages that do care (Python is the famous one) made a different trade, and both camps are firmly convinced.
The file is not the program. It is a description of one. Turning it into something that runs takes another step, which the next lesson is about.
Encoding: the bit that bites
If a file is characters, something has to decide which bytes mean which characters. That mapping is an encoding, and there is more than one.
Type café in a modern editor and it is saved as UTF-8. Five bytes for four characters:
bytes : 63 61 66 c3 a9
as UTF-8 : café
as Latin-1 : café
lengths : utf-8 -> 4 chars, latin-1 -> 5 charsc, a and f are one byte each. é is the pair c3 a9. Nothing in the file records which encoding was meant — the bytes are identical either way — so a program that assumes Latin-1 reads that pair as two separate characters and prints café.
Look at the last line, because it is the part that turns a display annoyance into a bug: the same file is four characters long or five, depending on who is reading it. A length check, a database column of VARCHAR(4), a substring, a truncation for a UI — all of them now disagree about the same data.
This is not a beginner's problem you outgrow. It is one of the most persistent bugs in backend work, because it appears at every boundary: a file read, a database column, an HTTP response, a name with an accent in it. The rule that saves you:
Comments, and what they are for
Some of the text is not for the machine at all:
// this line is ignored entirely
/* so is
this block */The compiler throws comments away. They exist purely for the next person, which is usually you in six months.
The useful discipline is what to write. A comment that repeats the code (// add one to i above i++) is noise that rots the moment the code changes. A comment that says why is the one worth having:
// Retry three times: the payment provider returns 503 during their
// nightly maintenance window and recovers within ~2 seconds.Nothing in the code could have told you that, and without it the next person deletes the retry.
Misconceptions
- "The IDE compiles my code as I type." It does compile continuously, which is why errors appear before you save — but the file on disk is still just text, and
javacon the command line produces the same result. The IDE is a convenience, not a component of the language. - "Formatting affects behaviour." In Java, almost never. It affects whether a reviewer can see what you meant, which matters more often than you would guess.
- "Encoding is legacy." It is 2026 and a name with an apostrophe still breaks somebody's export every week.