Methods, Arrays & Strings

Defining & Calling Methods

15 min Lesson 1 of 14

Defining & Calling Methods

In the programs you have written so far, all logic lives inside main. That works for tiny scripts, but it quickly becomes a problem: the code grows long, repetition creeps in, and changing one behaviour means hunting through hundreds of lines. Methods are Java's answer — they let you name a block of logic, reuse it anywhere, and change it in one place when requirements change.

Why Methods Matter

Think of a method as a named recipe. You write the recipe once ("how to make tea"), then call it by name every time you want tea — without rewriting the steps. In programming terms, methods provide:

  • Reusability — write once, call many times.
  • Readability — a name like calculateTax() tells a reader exactly what happens, without them reading every line inside.
  • Maintainability — fix a bug in one method and it is fixed everywhere that method is called.
  • Testability — small, focused methods are far easier to test in isolation.

Anatomy of a Method

Every Java method has the same basic structure — the method signature followed by the body:

accessModifier returnType methodName(parameterList) { // body return value; // only if returnType is not void }

Let us break each part down:

  • Access modifier — controls who can call the method. public means anyone; private means only code inside the same class. You will learn more modifiers later; for now use public static so the method can be called from main.
  • Return type — the data type of the value the method sends back. Use void when the method does not send anything back.
  • Method name — follows camelCase by convention: starts with a lowercase letter, each new word capitalised (calculateArea, printGreeting).
  • Parameter list — zero or more typed inputs. May be empty, in which case the parentheses are still required: ().

Your First Void Method

A void method performs an action but produces no result to give back to the caller. Printing a banner is a good example:

public class Demo { // A void method — it prints, but returns nothing public static void printWelcome() { System.out.println("=== Welcome to Java ==="); System.out.println("Let's learn methods!"); } public static void main(String[] args) { printWelcome(); // call it once printWelcome(); // call it again — no copy-paste needed } }

Running this prints the banner twice. Notice how main stays short and readable — it describes what happens rather than spelling out every println.

Methods That Return a Value

When a method computes something useful you declare a return type and use the return statement to hand the result back:

public class CircleCalculator { // Returns the area of a circle given its radius public static double circleArea(double radius) { return Math.PI * radius * radius; } public static void main(String[] args) { double area = circleArea(5.0); System.out.println("Area: " + area); // Area: 78.53981633974483 } }

The caller catches the returned value in a variable (area) and can then use it for further work — print it, store it, pass it to another method, whatever is needed.

The return type is a contract. If you declare double, the method must return a double on every possible path through the code. Java enforces this at compile time, so a missing return is a compile error, not a surprise at runtime.

Understanding the Call Stack

When a method is called, Java pushes a new stack frame onto the call stack. The frame holds the method's local variables and tracks where execution should return when the method finishes. When return (or the end of a void method) is reached, the frame is popped and execution resumes from where the call was made.

public class StackDemo { public static void sayHello() { System.out.println("Hello from sayHello!"); // frame for sayHello is popped here } public static void greetUser() { System.out.println("Preparing greeting..."); sayHello(); // push sayHello frame, then pop when done System.out.println("Greeting complete."); } public static void main(String[] args) { greetUser(); // push greetUser frame } } // Output: // Preparing greeting... // Hello from sayHello! // Greeting complete.

The call stack matters in practice because it is exactly what you see in a stack trace when an exception is thrown — each line of the trace is one frame, showing you the chain of method calls that led to the error.

Keep methods small and focused. A method that does exactly one thing is easier to name, easier to read, and easier to debug. If you find a method growing past 20–30 lines, consider whether it is really doing two separate jobs that could each become their own method.

Calling a Method: The Mechanics

To call a method you write its name followed by parentheses (with any required arguments inside):

// Calling a void method — the statement stands alone printWelcome(); // Calling a returning method — capture or use the result double area = circleArea(5.0); System.out.println(circleArea(3.0)); // use directly in another call

You can call a method from main, from another method, or even from within itself (recursion — covered in a later tutorial). Each call is independent: the method runs, returns, and the caller continues.

Forgetting the parentheses is a compile error. Writing printWelcome without () does not call the method — it is a reference to the method object, which is not what you want here. Always include () even when there are no arguments.

Putting It All Together

Here is a small program that uses both void and returning methods together:

public class Rectangle { public static double area(double width, double height) { return width * height; } public static double perimeter(double width, double height) { return 2 * (width + height); } public static void printInfo(double width, double height) { System.out.println("Width: " + width); System.out.println("Height: " + height); System.out.println("Area: " + area(width, height)); System.out.println("Perimeter: " + perimeter(width, height)); } public static void main(String[] args) { printInfo(4.0, 7.0); // Width: 4.0 // Height: 7.0 // Area: 28.0 // Perimeter: 22.0 } }

Notice how printInfo delegates to area and perimeter rather than inlining the calculations. Each method has a single clear responsibility.

Summary

A method is a named, reusable block of code with a declared return type (void or a specific type), a name, and an optional parameter list. Calling a method pushes a new frame on the call stack; when the method returns, the frame is popped and execution resumes in the caller. Keeping methods small and focused is the foundation of clean, maintainable Java code. In the next lesson you will explore how parameters and return values let methods communicate richer information with their callers.