Search⌘ K
AI Features

Defining and Calling Methods

Explore how to define and call methods in Java to structure your programs into reusable, focused actions. Understand method syntax, parameters, return types, and execution flow to build modular, maintainable applications that avoid monolithic code blocks and improve readability.

So far, all code has been written inside a single main method. Although this approach works for small programs, it becomes difficult to maintain as the codebase grows. In a production application, operations such as tax calculation, email dispatch, and user validation should not be implemented in a single monolithic block. This structure reduces readability and significantly increases maintenance overhead.

To solves this, we rely on Java methods. Think of them as the “verbs” of our code. They allow us to define an action once and perform it as many times as we need. By breaking our code into smaller, focused methods, we turn a chaotic list of instructions into a clean, readable story.

The anatomy of a method

A method is a named block of code that performs a specific task. Defining a method involves specifying its access level, return type, name, and any inputs it requires.

For now, we will define our methods as public static. We will explore access modifiers like public and private in depth later, but we need static here so our methods can be called directly from the main method.

Here is the syntax for a basic method:

Breakdown of the method’s syntax
Breakdown of the method’s syntax
  • Return type: Indicates what data the method sends back. void means it returns nothing.

  • Method name: Follows camelCase conventions. While any valid identifier works, best practice dictates using a verb-noun pair that clearly describes what the method does (e.g., calculateTotal, sendEmail).

  • Parameters: A list of variable(s) inside parentheses that receive input values. If no input is needed, the parentheses remain empty.

  • Body: The code block { ... } that executes when the method is called.

Invoking methods

Defining a method does not run it. To execute the code inside a method, we must call (or invoke) it. When we call a method, the program's control flow "jumps" from the current line to the method's body. Once the method finishes, control returns to exactly where it left off.

We can call a method as many times as we want, reusing the logic without rewriting it.

Java 25
public class MethodBasics {
// 1. Defining the method
public static void printGreeting() {
System.out.println();
System.out.println("Welcome to Java methods!");
System.out.println("Methods make code reusable.");
System.out.println();
}
public static void main(String[] args) {
System.out.println("Starting program...");
// 2. Calling the method
printGreeting();
System.out.println("Back in main.");
// 3. Reusing the method
printGreeting();
System.out.println("Program finished.");
}
}
  • Lines 4–7: We define printGreeting. It takes no inputs and returns nothing (void).

  • Line 13: The program pauses execution of main and jumps to line 4 to run printGreeting.

  • Line 15: After printGreeting finishes, execution resumes here.

  • Line 18: We call the method again, reusing the code defined in lines 4–7.

Passing data with parameters

A method that always does the exact same thing is limited. To make methods dynamic, we define parameters. Parameters act like variables declared inside the method’s parentheses.

When we call the method, we provide the actual values, known as arguments. The Java compiler ensures that the type of the argument matches the type of the parameter.

Java 25
public class ParameterExample {
// Method with two parameters
public static void printRectangleInfo(int width, int height) {
int area = width * height;
System.out.println("Rectangle: " + width + "x" + height + ", Area: " + area);
}
public static void main(String[] args) {
// Passing literal values as arguments
printRectangleInfo(5, 10);
// Passing variables as arguments
int w = 7;
int h = 3;
printRectangleInfo(w, h);
}
}
  • Line 4: We define two parameters: int width and int height. These variables only exist inside this method.

  • Line 5: We use the parameters width and height exactly like local variables to calculate the area.

  • Line 6: We print the formatted result to the console.

  • Line 11: We call the method with arguments 5 and 10. Inside the method, width becomes 5 and height becomes 10.

  • Line 16: We pass variables w and h. Their values (7 and 3) are copied into the method’s parameters.

Returning values

Often, we need a method to calculate a result and give it back to the code that called it. We do this by changing the return type from void to a specific data type (like int, double, or String) and using the return keyword.

The return statement immediately terminates the method and sends the specified value back to the caller.

Java 25
public class ReturnExample {
// Returns an int value
public static int calculateSquare(int number) {
int result = number * number;
return result; // Sends 'result' back to the caller
}
// Returns a boolean based on logic
public static boolean isEven(int number) {
if (number % 2 == 0) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
// Capture the returned value in a variable
int squareVal = calculateSquare(4);
System.out.println("Square of 4 is: " + squareVal);
// Use the returned value directly in an expression
if (isEven(squareVal)) {
System.out.println(squareVal + " is an even number.");
}
}
}
  • Lines 4–7: We define the calculateSquare method to compute the square of a number. The int keyword indicates it will return an integer result.

    • Line 6: The return statement immediately ends the method and sends the calculated result back to the caller.

  • Lines 10–16: The isEven method evaluates if a number is divisible by 2. It returns a boolean (true or false) to report the outcome.

  • Line 20: We call calculateSquare(4). The method runs, calculates 16, and returns it to be stored in the variable squareVal.

  • Line 24: We call isEven(squareVal) to check the number. Since 16 is even, the method returns true, causing the if block to execute.

Method execution flow

Methods can call other methods. This allows us to build complex logic by layering simple operations. When a method calls another, the new method is pushed onto the call stack; a temporary memory structure that tracks execution. The called method must finish completely before the previous method resumes.

Java 25
public class MethodChaining {
public static void processUser(String user) {
System.out.println("Processing " + user + "...");
boolean isValid = validateUser(user); // Calls another method
if (isValid) {
System.out.println("User " + user + " is valid.");
} else {
System.out.println("User " + user + " is invalid.");
}
}
public static boolean validateUser(String name) {
System.out.println("-> Validating name length.");
return name.length() > 3; // Returns true if name is longer than 3 chars
}
public static void main(String[] args) {
processUser("Ai");
System.out.println("---");
processUser("Java");
}
}
  • Line 20: The main calls processUser("Ai"). Control moves to line 3.

    • Line 5: processUser() pauses and calls validateUser(). Control moves to line 14.

    • Line 16: validateUser() returns false (length is 2). Control returns to line 5.

    • Line 7: processUser() resumes and executes the else block.

  • Line 21: processUser("Java") begins the cycle again.

Let's visualize exactly how Java manages these method calls in memory as the program runs:

canvasAnimation-image
1 / 22

By breaking our program into these small, interacting components, we move from writing monolithic scripts to building modular applications. This approach reduces redundancy, isolates bugs, and makes our code readable.