LLD Dojo

Java, from nothing · chapter 1 of 33

A class, an object, and main()

Chapter 1.1 · Part 1, Java from nothing · about 25 minutes

What you need before this chapter: nothing. This is the first chapter. If you have never written a line of Java, you are in the right place.

When you finish this chapter you will be able to:


1. The one idea in this chapter

A class is a description. An object is a thing that matches the description.

That is the whole idea, and it is worth being slow about, because every later chapter sits on top of it.

Think about a parking ticket. Somewhere there is a definition of what a parking ticket is: it has a number plate on it, and a time the car arrived. That definition is not itself a ticket. You cannot hand it to a driver. It is a description of the shape every real ticket will have.

Then a car arrives, and you print an actual ticket. Plate KA-01-4432, arrived at 9:15. That printed ticket is a real thing with real values in it. Another car arrives and you print a second ticket, with a different plate and a different time. Two real tickets, one description.

In Java, the description is a class and the real thing is an object. You write the class once. The program creates as many objects from it as it needs, each with its own values.

The word for "creating an object from a class" is instantiating, and an object is often called an instance. Those two words mean nothing more than what you just read, and interviewers use them constantly, so they are worth knowing from the first chapter.


2. Type this

Make a folder to work in. Inside it, create a file called exactly Ticket.java — capital T, and the extension .java. Java requires the file name to match the public class name inside it, so this is not a style choice; get it wrong and it will not compile.

Type this in. Do not copy and paste it. Typing it is slower, and that is the point: you will read every character, and you will hit the errors in section 5 yourself, which is how they stop being mysterious.

INLINECODE0


3. Run it

Java is a compiled language. That means two steps, every time: turn your source into class files, then run them. Open a terminal in the folder that holds Ticket.java and run:

INLINECODE1

The first command, javac, is the Java compiler. If your code is valid it prints nothing at all and creates a file called Ticket.class next to your source. Silence from javac is success, which feels wrong the first few times.

The second command, java, runs it. Note there is no .java and no .class on that line — you pass the class name, not a file name.

You should see exactly this:

INLINECODE2

If you got those three lines, the toolchain on your machine works and the rest of this course will run. If you got an error instead, section 5 almost certainly covers it.


4. What just happened, line by line

public class Ticket { declares the class — the description. public means other code is allowed to use it. Everything up to the matching closing brace is part of the description.

String plate; and int arrivedAtMinute; declare fields. A field is a named slot for a value that every object of this class will have its own copy of. String means text. int means a whole number. Java is statically typed: you must say what kind of value goes in a slot, and the compiler holds you to it.

Notice what these two lines do not do. They do not create a ticket, and they do not put any values anywhere. They are still part of the description.

public static void main(String[] args) { is where the program starts. When you type java Ticket, the JVM looks inside Ticket for a method with exactly this shape and runs it. Every word is load bearing:

WordWhat it does
publicthe JVM, which is outside your class, is allowed to call it
staticit belongs to the class itself, so it can run before any object exists
voidit returns nothing
mainthe exact name the JVM looks for
String[] argsthe command-line arguments, as an array of text; here, unused

static is the one that trips people up, and there is a neat reason for it. main has to run before your program has created anything. If main needed an object to exist first, you would have a chicken-and-egg problem: nothing could ever start. static means "attached to the class, not to any object", which is exactly what a starting point needs to be.

Ticket first = new Ticket(); is the line where a real object appears. new Ticket() builds one and hands it back. Ticket first declares a variable of type Ticket to hold it. From here on, first refers to a real object with its own two slots, both currently empty.

first.plate = "KA-01-4432"; puts a value in one of that object's slots. The dot means "reach into this object and get at the thing named on the right".

Ticket second = new Ticket(); builds a second, separate object. This is the sentence to hold on to: first and second are two independent objects from one class, and setting second.plate has no effect whatsoever on first.plate. The last three lines print values from each to prove it.

+ inside System.out.println glues text together. When one side is text, Java converts the other side to text and joins them.

That is why the subtraction needs its own brackets, and the reason is worth doing properly because it teaches you how Java reads a line. Operators of equal precedence are applied left to right, so without brackets Java reads this:

INLINECODE3

as ("minutes apart: " + 600) - 555. The first step glues 600 onto the text and produces "minutes apart: 600". The second step then tries to subtract 555 from a piece of text, which is meaningless, so the compiler stops you:

INLINECODE4

Getting a compile error here is good news. Java caught a nonsense operation before the program ever ran, which is the whole benefit of a statically typed language and a theme for the rest of the course: the compiler is a colleague who reads your code before you run it. Put the brackets back and the subtraction happens first, so what gets glued on is the number 45.


5. Three errors you are likely to hit

These are not hypothetical. They are the three you will actually meet, with the real messages.

The file name does not match the class name. Save the file as ticket.java with a lower-case t:

INLINECODE5

The fix is to rename the file. A public class must live in a file with exactly its own name.

You ran the wrong thing. Type java Ticket.java out of habit and older Java versions give you:

INLINECODE6

Pass the class name, java Ticket, with no extension.

You forgot new. Delete new Ticket() and write Ticket first; on its own, then try to set first.plate:

INLINECODE7

This one is worth pausing on. Ticket first; creates a variable, which is a place to hold a reference to an object. It does not create the object. Until you assign something, the variable holds nothing at all, and the compiler refuses to let you use it. The distinction between a variable and the object it points at is the subject of chapter 1.3, and it is the single most common source of confusion in early Java.


6. Your turn

Add a third ticket to main, plate TN-22-7788, arrived at minute 630. Then print how many minutes after the second ticket it arrived.

Do it before reading on. Compile and run it. The point is to hit your own typing errors now, in five lines you fully understand, rather than in chapter 1.7 where there is more going on.

The answer. Three lines added, and the same shape as before:

INLINECODE8

Running it prints third after second: 30. If you got 30, you have understood everything in this chapter.


7. Going deeper

Everything above is true and is enough to move on. This section goes past it, and it reframes what you just learned.

I said a class is a description and an object is a real thing. That is the right way to start, but it is not quite the whole truth. At runtime, the class is itself an object.

When you run java Ticket, the JVM loads Ticket and creates exactly one object to represent the class itself. You can hold it, print it, and compare it. Add this to a scratch file and run it:

INLINECODE9

Output:

INLINECODE10

Read the third line again. Deep.class and a.getClass() are the same object. There is one class-object per class, created once when the class is loaded, shared by every instance forever.

Now static stops being a rule you memorise. Earlier I said static means "belongs to the class, not to any object", and you had to take that on trust. You can now see it literally: there is a real object for the class, and static members live on that object. Two Deep instances have two separate plate slots, but they do not each have a ticketsPrinted, because that one belongs to the single class-object they share. main can run before any instance exists for exactly the same reason — the class-object is already there.

This has consequences you will meet later, and they are worth knowing early:

You do not need to use any of this now. You need to know that the description you write becomes a real thing at runtime, because "static means it's on the class" is a sentence most people repeat for years without ever having seen the class it is talking about.

8. Why this matters in an interview

This is chapter 1.1, so nothing here is impressive on its own. But two habits start now and get graded later.

The first is that a class is a description of one kind of thing. When you are asked to design a parking lot in forty minutes, your first move will be listing the kinds of things that exist — ticket, spot, vehicle, fee. Each becomes a class. Interviewers watch that step closely, because a candidate who cannot name the nouns cannot start.

The second is smaller and shows up in every round: first and second are separate objects. Almost every concurrency bug in Part 4, and a good number of the design bugs before it, come down to two pieces of code disagreeing about whether they are looking at the same object or two different ones.

One honest warning before you move on. The code in this chapter has a real flaw that an interviewer at Uber, Atlassian or Salesforce would notice immediately: the fields are wide open, so any code anywhere can reach in and change a ticket's plate to nonsense after the fact. That is not a mistake in the chapter — it is the problem chapter 2.1 exists to solve, and you cannot appreciate the fix before you have seen the thing it fixes.


Next: chapter 1.2, Fields, methods, and constructors — where the ticket learns to set its own values up correctly, instead of trusting whoever created it to remember.

All chapters · 1.2 Fields, methods, and constructors →