Introduction to Methods in Java
Table of Contents + −
In the last lesson you learned about Java LocalDateTime. So far your code has lived inside one big main method, which is fine for tiny programs but does not scale. Java’s answer is the method: a named block of code you write once and use again and again.
🤔 Why do we need methods?
Picture a program that greets people in several places. Without methods, you copy the same lines every time.
System.out.println("Hello! Welcome.");System.out.println("Please enjoy your stay.");// ... later, the same two lines again ...// ... and again somewhere else ...If the greeting must change, you have to find every copy and edit each one. Miss one and that spot shows the old text. A method removes that pain. Here is why it helps:
- No repetition. Write the logic once. Call it as many times as you like.
- Easy changes. Fix one spot. Every call gets the fix for free.
- Readable code. A name like
calculateTotal()says what is happening at a glance. - Divide and conquer. Break a big problem into small named pieces.
Think of a method like a recipe card. You write the recipe once, then anyone in the kitchen follows it whenever they want the dish. A method is that card for your code.
🧩 The anatomy of a method
This is the skeleton every method follows.
accessModifier returnType methodName(parameterList) { // the body: code that runs when you call the method return value; // only if the method returns something}Each part from left to right:
- accessModifier controls who can call it.
publicmeans anyone;privatemeans only the same class. You can leave it off for now. - returnType is the kind of value handed back, like
int,String, ordouble. If nothing is handed back, you writevoid. - methodName is the name you call it by. Use a verb, like
printGreetingoraddNumbers. - parameterList is the inputs, inside the round brackets. Empty brackets
()mean it takes nothing. - body is the code inside the curly braces. This is what runs. To return a value, the body uses the
returnkeyword.
We go deep on parameters in the next lesson and on return values after that.
💡 Your first method
Let’s write a method that prints a greeting. It takes no inputs and hands nothing back, so its return type is void.
public class Greeter {
// ✅ define the method once, at the class level static void printGreeting() { System.out.println("Hello! Welcome."); System.out.println("Please enjoy your stay."); }
public static void main(String[] args) { printGreeting(); // ✅ call it System.out.println("---"); printGreeting(); // ✅ call it again }}Here is how it works:
- We define
printGreetingonce, with the two print lines inside. - We call it by writing its name with brackets:
printGreeting(). That runs the code inside. - We call it twice, so the greeting prints both times with no copy-pasted text.
- Change the one definition and both calls follow.
Output
Hello! Welcome.Please enjoy your stay.---Hello! Welcome.Please enjoy your stay.The two greetings sandwich the --- line, matching the order of the calls in main, top to bottom.
➡️ How control jumps in and back
When the program reaches a method call, the flow of control does this:
- The program pauses at the call line in
main. - Control jumps into the method body and runs it top to bottom.
- When the method finishes (closing brace or a
return), control jumps back to the line that called it. - The program continues with the next line after the call.
A call is like a short detour. You leave the main road, do the work, then come back to where you left. The main method picks up right where it paused.
public class Flow {
static void doWork() { System.out.println("2. inside doWork"); System.out.println("3. still inside doWork"); }
public static void main(String[] args) { System.out.println("1. before the call"); doWork(); // control jumps into doWork here System.out.println("4. back in main"); }}The numbers in the output show the path control takes.
Output
1. before the call2. inside doWork3. still inside doWork4. back in mainSo main runs line 1, jumps into doWork for lines 2 and 3, then returns and runs line 4. The control flow always comes back to where the call was made, automatically.
↩️ void versus returning a value
Methods come in two flavours:
- A
voidmethod does work but hands nothing back. Printing is the classic example. - A value-returning method hands a result back. That returned value is the reason you called it.
Here is a method that returns an int instead of printing.
public class Calc {
// ✅ returns an int, so the return type is int (not void) static int addNumbers(int a, int b) { int sum = a + b; return sum; // hand the result back to the caller }
public static void main(String[] args) { int total = addNumbers(3, 5); // catch the returned value System.out.println("Total is " + total); }}The difference shows in two places:
- The return type is
int, notvoid. That promises anintcomes back. - The body uses
return sum;. The momentreturnruns, the method ends and the value travels back.
In main, the call addNumbers(3, 5) is replaced by its returned value, 8. We store that in total and print it.
Output
Total is 8The simple rule:
- If a method just does something, like printing, use
void. - If a method works out an answer you want to use later, give it a real return type and
returnthe answer.
⚙️ Static versus instance methods
You have seen static on every method so far. There are two kinds of methods in Java:
- A static method belongs to the class itself. You can call it without making an object first.
- An instance method belongs to an object. You must create an object before you call it (covered in the classes lessons).
main is static, so Java can start your program by calling it directly. And static main can only call other static methods directly. That is why we mark printGreeting and friends as static here: so main can call them by name, no object in the way.
This shows a static method called directly from static main.
public class Banner {
// ✅ static method: callable directly from static main static void showBanner() { System.out.println("=== FreeCodingSchool ==="); }
public static void main(String[] args) { showBanner(); // direct call, no object created }}Output
=== FreeCodingSchool ===Don't overthink static yet
For now, static just means “callable directly without an object.” That is all you need so your methods work next to main. You will learn the full story, and meet instance methods, when we reach classes and objects. Until then, include static and keep moving.
Read static as “belongs to the class, not to an object.”
🔁 The DRY idea: don’t repeat yourself
DRY stands for “Don’t Repeat Yourself.” Every piece of logic should live in exactly one place. If you see the same lines copied around, a method is waiting to be born. Here is why it matters:
- One source of truth. Logic in one place means you know where to look and where to change it.
- Fewer bugs. Copies drift apart; you fix one and forget the rest. One definition cannot drift from itself.
- Less to read. Three short calls beat thirty repeated lines.
So whenever you are about to copy-paste a block of code, stop. That is the signal to write a method.
🛠️ Worked example: refactoring repeated code
Here is a receipt printer written the messy way, with the divider line repeated four times.
public class ReceiptBefore {
public static void main(String[] args) { // ❌ the same divider copied again and again System.out.println("----------------------------"); System.out.println(" Coffee House"); System.out.println("----------------------------"); System.out.println("Latte ......... $4.50"); System.out.println("Muffin ........ $3.00"); System.out.println("----------------------------"); System.out.println("Total ......... $7.50"); System.out.println("----------------------------"); }}It works, but the divider is written four times. Change its look and you must edit four lines and keep them identical. That is the pain DRY warns about.
Now let’s refactor it: improve the structure without changing what the program does. We pull the divider into one method and call it where needed.
public class ReceiptAfter {
// ✅ the divider lives in one place static void printDivider() { System.out.println("----------------------------"); }
public static void main(String[] args) { printDivider(); System.out.println(" Coffee House"); printDivider(); System.out.println("Latte ......... $4.50"); System.out.println("Muffin ........ $3.00"); printDivider(); System.out.println("Total ......... $7.50"); printDivider(); }}Both versions print the same receipt.
Output
---------------------------- Coffee House----------------------------Latte ......... $4.50Muffin ........ $3.00----------------------------Total ......... $7.50----------------------------What we gained:
- The divider is written once. Want dots instead of dashes? Change one line and all four update at once.
mainreads better.printDivider()says “draw a divider here” in plain words.
⚠️ Common Mistakes
A few slip-ups trip up almost everyone at the start. Here is the wrong way and the right way side by side.
Forgetting to call the method. Defining a method does not run it. The code runs only when you call it by name.
static void sayHi() { System.out.println("Hi!");}
public static void main(String[] args) { // ❌ method is defined but never called, so nothing prints}public static void main(String[] args) { sayHi(); // ✅ now the method actually runs}Using the wrong return type. If a method returns a value, the return type must match that value. Saying void but then trying to return a number does not compile.
// ❌ says void, but tries to return an intstatic void getScore() { return 10;}// ✅ return type matches what you returnstatic int getScore() { return 10;}Defining a method inside another method. Methods sit inside the class, beside main. You cannot nest one inside another. Picture the class as a box with the methods lined up next to each other, not stacked.
public class Bad { public static void main(String[] args) { // ❌ a method cannot be defined inside main static void helper() { System.out.println("nope"); } }}public class Good { // ✅ helper sits beside main, at the class level static void helper() { System.out.println("works"); }
public static void main(String[] args) { helper(); }}Forgetting the brackets when calling. To call a method you write sayHi() with brackets. Just sayHi on its own does not call it.
✅ Best Practices
A few habits keep your methods clean from day one:
- One job per method. If you describe it with “and”, like “prints the menu and reads the choice”, that is two methods.
- Name it with a verb.
printGreeting,calculateTotal,isValid. The name says what it does so the reader skips the body. - Keep methods short. Small methods are easier to read, test, and reuse. If one grows long, split off named pieces.
- Reach for a method when you copy-paste. Duplicating a block is the signal to make a method.
🧩 What You’ve Learned
Nicely done. Let’s recap methods.
- ✅ A method is a named, reusable block of code you define once and call many times.
- ✅ A method’s anatomy is access modifier, return type, name, parameter list, and body.
- ✅ Calling a method makes control jump in, run the body, then jump back to the next line after the call.
- ✅
voidmeans the method returns nothing; a real return type means it hands a value back withreturn. - ✅ A static method is callable directly without an object, which is why
mainis static. - ✅ The DRY idea says don’t repeat yourself; pull repeated code into one method so there is a single source of truth.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What is the main reason to use methods?
Why: Methods let you define logic once and call it many times, so you do not repeat yourself.
- 2
What does a return type of void mean?
Why: void means the method does its work but does not return a value.
- 3
How do you run a method's code?
Why: Defining a method does not run it; you must call it, like printGreeting().
- 4
Where are methods defined in Java?
Why: Methods are defined at the class level, alongside main, not inside another method.
🚀 What’s Next?
Our methods so far take no input. But most methods need data to work with, like the numbers to add or the name to greet. That data comes in through parameters. Let’s learn how to pass information into a method.