The canteen token
The college canteen gives every order a token number. Riya wants a program that prints the token and the date. She writes it, it works, and then Arjun Sir points at the first line inside the class and asks: “What does each of those five words do?”
public static void main… honestly, Sir, I just copy it every time. I know it has to be there, but not why.
Most students do. But each word is an answer to a question the JVM asks. Can I call it from outside? public. Do I need an object first? static. Will you hand me back a result? void. Which method do I start with? main.
And String[] args is the words typed after the class name, from the last lesson!
Right. Today we'll take your token program apart, piece by piece, and you'll never have to copy it blindly again.
What is the structure of a Java program?
A Java source file has an optional package declaration, followed by zero or more import statements, followed by one or more type declarations (classes, interfaces, enums or records), of which at most one is public. A class contains members: fields (variables) and methods. Executable code is written as statements inside method bodies, grouped into blocks with curly braces. An application starts from the method public static void main(String[] args).
Think of the file as a building. The package is its address. Imports are the things you bring in from outside. The class is the building itself. Fields are what's stored inside, methods are the rooms where work happens, and statements are the individual jobs done in each room. main is the front door, where the JVM always walks in.
Words you'll meet in this lesson
;. Example: int token = 42;{ }. Class bodies, method bodies and loop bodies are blocks.public, class, static, void, int…//, /* */ and /** */.The order inside a .java file
| 1. package (optional) | package com.myphatshala.canteen; First line if present. Says which folder/group the class belongs to. |
|---|---|
| 2. import (optional) | import java.time.LocalDate; Lets you use a class by its short name. java.lang (String, System, Math) is imported automatically. |
| 3. class declaration | public class Main { … } At most one public class per file. |
| 4. fields | Variables inside the class: static String canteen = "…"; |
| 5. methods | main plus any helper methods, in any order |
| 6. statements | Inside method bodies only, each ending with ; |
Exam tip: the order is package → import → class, and it can't change. Inside a class, fields and methods can appear in any order, but statements like System.out.println(…) can't sit directly in a class body: they must be inside a method (or an initialiser block).
The building blocks, one by one
Every word of the main method
| Word | Meaning | Why the JVM needs it |
|---|---|---|
public | Access modifier: anyone can call this method | The JVM calls it from outside your class |
static | Belongs to the class, not to an object | The JVM can call it without creating a Main object first |
void | Return type: returns nothing | The JVM doesn't expect a value back (exit codes use System.exit) |
main | The method's name | The launcher looks for exactly this name |
String[] args | Parameter: an array of Strings | Receives the command-line arguments |
Allowed variations: String args[], String... args, any parameter name (String[] input), and the order static public all work. Changing void, removing static or public, or renaming main means classic Java won't find it as the entry point.
Three kinds of comments
Single-line: //
Everything after // to the end of the line is ignored. Used for short notes.
Multi-line: /* … */
Everything between the markers is ignored, across many lines. Handy for longer explanations.
Blocks of textDocumentation: /** … */
Placed just above a class or method. The javadoc tool turns these into HTML documentation, like the official Java API pages.
Kinds of statements you'll write
| Kind | Example | Covered in |
|---|---|---|
| Declaration | int token = 42; | Module 2 |
| Expression statement | token = token + 1; · printToken(token); | Modules 2 and 5 |
| Control flow | if (token > 100) { … } · for (…) { … } | Module 3 |
| Return | return total; | Module 5 |
| Block | { statement1; statement2; } | Everywhere |
Build the token program, one layer at a time
Instead of copying the whole program, add one structural piece per step and see why each one is there.
Start with an empty class
This compiles, and javac even adds a default constructor. Butpublic class Main { }java Mainfails with “Main method not found”: the JVM has a building with no front door.Add the main method
Now the launcher findspublic class Main { public static void main(String[] args) { int token = 42; System.out.println("Token #" + token); } }Token #42main, creates theargsarray, and runs the two statements in order, top to bottom.Add a field and a helper method
The canteen name belongs to the whole program, so it becomes a field. Printing a token is a job we may repeat, so it becomes a method.
The field isstatic, so it's stored once with the class, not inmain's stack frame. CallingprintToken(token)pushes a new stack frame on top ofmain's.Import a class from the library
To print the date we use
An import doesn't copy any code into your file. It only tells javac thatLocalDatefrom thejava.timepackage, so we addimport java.time.LocalDate;at the top.LocalDatemeansjava.time.LocalDate. In the .class file, the full name is stored in the constant pool.Add comments and check the layout
Add a short comment above the class and indent each block by four spaces. Your final program is in Part 7.
javac throws comments and extra spaces away completely: the .class file is identical with or without them. They exist purely for the humans who read the code later, including you.
public static void main, word by word: both views
Step through the most famous line in Java. Left: the code, with one word highlighted. Right: the question the JVM is asking at that moment.
- public: an access modifier. Code anywhere, including the JVM, may call this method.
- static: the method belongs to the class, so it can be called without creating an object.
- void: the return type.
mainreturns nothing. - main: the exact name the launcher looks for. Java is case-sensitive.
- String[] args: the command-line words, delivered as an array of Strings.
- Inside main,
System.out.printlnis a class, an object and a method, joined by dots.
- The JVM's launcher is outside your class, so
mainmust be public for it to be called. - When the program starts, no objects exist. A static method belongs to the loaded class, so the JVM can call it right away.
- In bytecode, main's descriptor is
([Ljava/lang/String;)V: a String array in, V (void) out. - The launcher searches the class for the exact signature. A different name or case doesn't count.
- The words after the class name become a String array on the heap, and
argsrefers to it. Systemis a class,outis its static field holding a PrintStream object, andprintlnis that object's method.
How real projects are structured
Company projects follow the same rules, just with many more files. Here's how the structure you learned scales up.
Watch it with an example: a three-class fee app
Real programs have many classes. Watch how the JVM starts from the one class that has main and loads the others only when they are needed.
- java App: you name the class that has
main. The JVM loadsApp.classfirst. - main starts: the JVM calls
App.main(args). This is the only method it calls on its own. - new Student(...): main uses Student for the first time, so now the JVM finds and loads
Student.class. - Fee.amount(...): the same happens for Fee. Classes are loaded lazily, on first use.
- Output: main prints the result and ends. One file per public class, one
mainto start: that's the structure of every Java app, big or small.
1. Packages organise thousands of classes
A banking app might have hundreds of classes. They're grouped into packages such as com.bank.payments and com.bank.accounts, which are also folders on disk. Every file starts with its package line.
2. A tiny main in a big application
In a Spring Boot service, main is often just one line: SpringApplication.run(App.class, args);. It starts the framework, which then creates and wires all the other classes.
3. Javadoc comments become API documentation
Libraries document every public class and method with /** … */ comments. The javadoc tool turns them into web pages, and IDEs show them as pop-up help while you type.
4. Batch jobs driven by args
Night-time jobs, such as generating monthly statements, are often started by a scheduler with command-line arguments: java -jar report.jar --month=10. The values arrive in args, and the job's exit code tells the scheduler whether it succeeded.
5. Style checks in code review
Teams agree on layout and naming rules (indentation, braces, one class per file), and tools such as Checkstyle or the IDE's formatter check them automatically before code is merged.
Examples are simplified to show the structure. Project layouts vary between companies and frameworks.
The complete token program
Every structural piece from this lesson in one program. Read the notes, then try the challenges.
import java.time.LocalDate;
/* Prints a canteen token with today's date. */
public class Main {
static String canteen = "Kharghar Canteen";
public static void main(String[] args) {
int token = 42;
printToken(token);
System.out.println("Date: " + LocalDate.of(2026, 10, 15));
}
// A helper method: prints one token line
static void printToken(int number) {
System.out.println(canteen + " - Token #" + number);
}
}import java.time.LocalDate;Lets us writeLocalDateinstead ofjava.time.LocalDate. Must come before the class./* … */and// …Comments. javac ignores them completely.static String canteen = …;A field: declared in the class, outside every method, so every method can use it.printToken(token);A method call statement. Java jumps intoprintToken, runs it, and comes back.static void printToken(int number)A helper method with one parameter. It'sstaticsomaincan call it without an object.{ }and indentationBraces mark where each block starts and ends. Indentation is only for humans, but makes the blocks easy to see.
Follow the program from main into a method and back
Watch the stack: when main calls printToken, a new frame goes on top, and it's removed when the method returns. The static field lives with the class, not in any frame.
Worked examples: real problems, solved and traced in memory
Every Java program has the same skeleton: imports, a class, fields, methods and main. These three programs use each part for a real job. In the trace, watch static fields appear once for the class while each method call gets its own frame.
Token slips from a helper method
Problem statement
A restaurant prints a token slip for each order. The restaurant name is the same for every slip, so store it once in a static field. Put the printing in a method and call it for tokens 101 and 102.
tokens 101, 102
Udupi Corner | Token #101 Udupi Corner | Token #102 Slips printed: 2
Approach
- A
static Stringfield holds the name: one copy for the whole class. printSlip(int token)prints one slip.- main calls it twice.
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.
Using an import: a library book's due date
Problem statement
A college library lends books for 14 days. Print the issue date and the due date. LocalDate lives in package java.time, so it must be imported at the top of the file.
issued 2026-10-15, 14 days
Issued: 2026-10-15 Due: 2026-10-29
Approach
import java.time.LocalDate;before the class.- Create the issue date, then
plusDays(14). - Print both.
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.
Two methods working together
Problem statement
A shop computes a bill in two steps: apply a 10% discount, then add 5% tax. Write one method for each step and combine them in main.
price 800
After discount: Rs 720.0 Final price: Rs 756.0
Approach
discount(double p)returns 90% of p.addTax(double p)returns 105% of p.- main passes the result of one method into the other.
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 1.6 in one screen
- File order: package → imports → class. One public class per file, named like the file.
- Class members: fields (data) and methods (behaviour). Statements live inside methods.
- public (JVM can call it) · static (no object needed) · void (returns nothing) · main (fixed name) · String[] args (command-line words).
System= class,out= static PrintStream field,println= method.java.langis auto-imported. Imports don't copy code; they just shorten names.- Comments:
//,/* */,/** */(javadoc). javac ignores them. - A method call pushes a new stack frame; returning pops it.
Interview and viva questions
Explain public static void main(String[] args).
public so the JVM can call it from outside the class; static so it can be called without creating an object; void because it returns nothing; main is the name the launcher looks for; String[] args receives command-line arguments as an array of strings.
Can we overload the main method?
Yes. You can write other methods named main with different parameters, such as main(int x). But the JVM only uses main(String[] args) as the entry point; the others are normal methods you call yourself.
Can a program run without a main method?
A normal application needs an entry point. Very old Java versions could run code from a static block without main, but that stopped working in Java 7. Frameworks and app servers do have a main; it's just inside the framework rather than your code.
What is the difference between import and #include in C?
#include copies the header file's text into your source before compiling. Java's import copies nothing: it only tells the compiler which full class name a short name refers to. Classes are loaded separately by the JVM at run time.
Why does Java use System.out.println instead of just print?
Because everything in Java belongs to a class. Printing is done by a PrintStream object stored in the static field out of the System class. This design also lets programs redirect System.out to a file or another stream.
Practice problems
Use the parts of a Java program: class, main, static fields, constants, imports and methods. Every output is fixed. The last three are business tasks.
A greeting method
Write static void greet() that prints "Welcome!" and call it from main twice.
(none)
Welcome! Welcome!
Show solution and explanation
public class Main {
static void greet() {
System.out.println("Welcome!");
}
public static void main(String[] args) {
greet();
greet();
}
}How it works: a method is defined once and can be called many times.
A constant
Declare static final double GST = 0.18; and print the GST on Rs 1,000.
1000
GST: Rs 180.0
Show solution and explanation
public class Main {
static final double GST = 0.18;
public static void main(String[] args) {
System.out.println("GST: Rs " + 1000 * GST);
}
}How it works: final means it can't be changed; constants are written in capitals by convention.
Method with a parameter
Write static int doubleIt(int n) and print doubleIt(21).
21
42
Show solution and explanation
public class Main {
static int doubleIt(int n) {
return n * 2;
}
public static void main(String[] args) {
System.out.println(doubleIt(21));
}
}How it works: return sends a value back to the caller.
Import and use
Import java.time.LocalDate and print the weekday of 2026-08-15.
2026-08-15
SATURDAY
Show solution and explanation
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
System.out.println(LocalDate.of(2026, 8, 15).getDayOfWeek());
}
}How it works: imports go before the class and let you use the short class name.
Shared counter
A static field visits starts at 0. A method visit() adds 1. Call it three times and print visits.
(none)
Visits: 3
Show solution and explanation
public class Main {
static int visits = 0;
static void visit() {
visits = visits + 1;
}
public static void main(String[] args) {
visit();
visit();
visit();
System.out.println("Visits: " + visits);
}
}How it works: a static field lives as long as the class, so every call updates the same value.
Delivery charge method
Write static int delivery(int km): Rs 20 base + Rs 8 per km. Print charges for 3 km and 7 km.
3, 7
3 km: Rs 44 7 km: Rs 76
Show solution and explanation
public class Main {
static int delivery(int km) {
return 20 + 8 * km;
}
public static void main(String[] args) {
System.out.println("3 km: Rs " + delivery(3));
System.out.println("7 km: Rs " + delivery(7));
}
}How it works: putting the rule in one method means a price change is made in one place. (Illustrative rates.)
Shop details in constants
Store the shop name and GSTIN as constants and print a receipt header.
(none)
Patil Electronics GSTIN: 27ABCDE1234F1Z5
Show solution and explanation
public class Main {
static final String SHOP = "Patil Electronics";
static final String GSTIN = "27ABCDE1234F1Z5";
public static void main(String[] args) {
System.out.println(SHOP);
System.out.println("GSTIN: " + GSTIN);
}
}How it works: constants for fixed business details avoid typos repeated across a program. (Made-up GSTIN.)
Two-step salary calculation
Write gross(basic) = basic + 40% HRA and net(gross) = gross − 12% PF. Print net for basic Rs 30,000.
30000
Net: Rs 36960.0
Show solution and explanation
public class Main {
static double gross(double basic) {
return basic * 1.40;
}
static double net(double gross) {
return gross * 0.88;
}
public static void main(String[] args) {
System.out.println("Net: Rs " + net(gross(30000)));
}
}How it works: the inner call runs first (42000.0), its result feeds the outer call (36960.0). (Simplified salary rules.)
Real-world scenario questions (asked in company interviews)
Structure questions in companies are about readability, maintainability and how programs talk to the systems around them. Decide your answer first, then open the model answer.
A 400-line main method
You're asked to review a teammate's billing utility. Everything is written inside main: reading the input file, calculating GST, applying discounts, writing the report. It works, but it's 400 lines long. What feedback would you give?
The interviewer is checking: do you understand why code is split into methods, and can you give review feedback politely and concretely?
Show a strong answer
I'd first say what works: the logic is correct and the output is right. Then I'd suggest structure:
- Split it into methods that each do one job, with clear names:
readOrders(),calculateGst(),applyDiscount(),writeReport(). Thenmainreads like a short summary of the steps. - Small methods can be unit-tested one at a time, for example testing GST rules without reading any files.
- Repeated code becomes one method called many times, so a rule change happens in one place.
- Later, related methods can move into their own classes (Module 6).
Avoid: “This is bad code, rewrite it.” Review comments should be specific and suggest the next step.
The failed job that reported success
A nightly Java job generates account statements. One night the database was down. The job printed an error, but the scheduler marked the run as successful, so nobody was alerted and customers got no statements. The main method catches every exception and prints it. What went wrong?
The interviewer is checking: do you know that main returns void and that the process exit code is how a Java program reports success or failure to the outside world?
Show a strong answer
Schedulers judge a job by its exit code: 0 means success, anything else means failure. Because main caught the exception, printed it and then returned normally, the JVM exited with code 0.
- After logging the error, call
System.exit(1)(or another non-zero code) so the scheduler sees the failure and raises an alert. - Alternatively, let the exception escape
main: an uncaught exception also makes the JVM exit with a non-zero code. - Use a proper logger instead of printing, and add an alert or retry policy in the scheduler.
Avoid: catching every exception in main just to “keep it from crashing”. Hiding failures is worse than crashing.
System.out.println in a server
Your first feature works, and you've added System.out.println calls to show what's happening. In review, the senior says: “Please don't use System.out in the service, use the logger.” You know println works. Why does it matter?
The interviewer is checking: do you understand what System.out is, and why real systems need structured logging?
Show a strong answer
System.out is just one PrintStream to standard output. A logging framework (for example SLF4J with Logback) adds what production needs:
- Levels (DEBUG, INFO, WARN, ERROR) that can be switched on or off without changing code.
- Automatic timestamps, thread names and class names on every line, which are essential when debugging.
- Sending logs to files or central systems (like an ELK stack), with rotation so disks don't fill up.
- Consistent formatting that monitoring tools can search and alert on.
Avoid saying: “println is the same thing.” It works for learning, not for operating a service.
Naming that fails the style check
Your pull request is blocked by the automated style check. It flags a class named paymentprocess, a method named Calculate_Total, and a file with two public classes. A teammate says, “It compiles, so who cares?”
The interviewer is checking: do you know Java's naming conventions and the structural rules, and why teams enforce them?
Show a strong answer
- Two public classes in one file won't even compile. One of them must move to its own file named after it.
- Java conventions: classes in PascalCase (
PaymentProcessor), methods and variables in camelCase (calculateTotal), constants in UPPER_SNAKE_CASE (MAX_LIMIT), packages in lowercase (com.shop.payments). - Conventions make code instantly readable to every Java developer and keep a large codebase consistent. Automated checks stop small issues taking up reviewers' time.
- I'd fix the names (the IDE's Rename refactoring updates every usage) and push again.
Avoid saying: “It compiles, so it's fine.” Code is read far more often than it's written.