Java · Beginner

Methods in Java

9 min readUpdated September 24, 2026Every example verified

In short: A method is a named block of code that takes parameters, does one job and optionally returns a value: static int area(int w, int h) { return w * h; }. Calling it copies the argument values into the parameters and runs the body; Java always passes arguments by value.

Naming a piece of work

Once a program does the same calculation in two places, or main grows past a screen, the code needs to be split into named pieces. A method is such a piece: it has a name, takes zero or more inputs called parameters, and may hand back a result. Calling the method by name runs its body. The benefits are the ones every good name gives: the call site reads as a sentence, the logic lives in one place, and that one place can be tested on its own.

A method declaration has a fixed order of parts. First come modifiers; the methods in this lesson are static, which means they belong to the class and can be called straight from main without creating an object. Then the return type, which is void when the method returns nothing. Then the name, by convention a lowerCamelCase verb phrase such as parcelCost or isValidPin. Then the parameter list in parentheses, each parameter written as a type and a name. The body in braces follows.

The return statement ends the method immediately and, for a non-void method, supplies the value. A method with a return type must return on every possible path; the compiler rejects one that can fall off the end without returning, with missing return statement. Several return statements are fine and often clearest: a validation method can return false as soon as it finds a problem and return true at the end, which is called an early return. In a void method a bare return; exits early.

When the method is called, each argument is evaluated and its value is copied into the corresponding parameter. This is pass by value, and Java has no other mode. For a primitive, the method gets a copy of the number and cannot change the caller's variable. For an array or other object, the value copied is the reference, so the method can modify the elements of the caller's array, but reassigning the parameter to a new array affects only the copy. Both behaviours follow from one rule: the parameter is a new variable initialised with the argument's value.

A class may hold several methods with the same name as long as their parameter lists differ in number or types. This is overloading; the compiler picks the version whose parameters match the arguments. Overloading by return type alone is not allowed, because the compiler could not tell the calls apart. A three-argument largest that calls the two-argument one twice is the typical use.

Variables declared inside a method, including its parameters, are local: they come into existence when the method is called and vanish when it returns. Two methods may both use a variable named total without interfering, and main cannot see a variable declared inside parcelCost. Inputs travel in through parameters and results out through the return value, which is what makes a method reusable.

A method may call itself, which is recursion; the recursion lesson covers when that is the right tool. Methods that belong to objects rather than to the class, written without static, are the subject of the classes and objects lesson.

Syntax

 Java · syntax
static returnType name(type param1, type param2) {
    // body; may use param1 and param2
    return value;            // required unless returnType is void
}

static void name(type param) {
    // no result; a bare return; exits early
}

result = name(arg1, arg2);   // call: arguments are copied into the parameters
name(arg);                   // call a void method as a statement

The method's signature is its name plus the parameter types. Overloads must differ in signature; the return type is not part of it.

Defining and calling methods

A courier's price rule written once and used three times, plus a void method that prints a label.

 Java
public class Main {
    static double parcelCost(double weightKg) {
        if (weightKg <= 1) {
            return 4.0;
        }
        return 4.0 + (weightKg - 1) * 1.5;
    }

    static void printLabel(String city, double cost) {
        System.out.println(city + ": " + cost);
    }

    public static void main(String[] args) {
        printLabel("Leeds", parcelCost(0.5));
        printLabel("Cork", parcelCost(3));
        double total = parcelCost(2) + parcelCost(1);
        System.out.println("Total: " + total);
    }
}

Output

Leeds: 4.0
Cork: 7.0
Total: 9.5

parcelCost takes a double and returns a double; the first return handles light parcels and exits before the second line runs. Passing the int literal 3 is fine because int widens to double. The result of one call becomes the argument of another in printLabel("Cork", parcelCost(3)). printLabel returns nothing, so it is called as a statement rather than inside an expression.

Early return and overloading

A PIN validator that stops at the first problem, and two methods that share a name. The program is run with the input 0473.

 Java
import java.util.Scanner;

public class Main {
    static boolean isValidPin(String pin) {
        if (pin.length() != 4) {
            return false;
        }
        for (int i = 0; i < pin.length(); i++) {
            if (!Character.isDigit(pin.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    static int largest(int a, int b) {
        return a > b ? a : b;
    }

    static int largest(int a, int b, int c) {
        return largest(largest(a, b), c);
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String pin = in.nextLine();
        System.out.println(pin + " valid: " + isValidPin(pin));
        System.out.println("7a31 valid: " + isValidPin("7a31"));
        System.out.println(largest(4, 9));
        System.out.println(largest(4, 9, 2));
    }
}

Input given to the program: 0473

Output

0473 valid: true
7a31 valid: false
9
9

isValidPin returns false the moment it sees a wrong length or a non-digit, so the loop never needs a flag variable; reaching the final return true means every check passed. The two largest methods have different parameter counts, so largest(4, 9) and largest(4, 9, 2) each pick the matching one, and the three-argument version reuses the two-argument one instead of repeating the comparison.

Arguments are passed by value

One method tries to change an int, the other changes an element of an array. Only one of them affects the caller.

 Java
public class Main {
    static void tryToChange(int n) {
        n = n + 100;
        System.out.println("inside: " + n);
    }

    static void markSold(int[] stock, int index) {
        stock[index] = 0;
    }

    public static void main(String[] args) {
        int count = 5;
        tryToChange(count);
        System.out.println("after: " + count);

        int[] shelf = {3, 8, 2};
        markSold(shelf, 1);
        System.out.println(shelf[0] + " " + shelf[1] + " " + shelf[2]);
    }
}

Output

inside: 105
after: 5
3 0 2

n is a copy of count; adding 100 changes the copy, and count is still 5 afterwards. stock is a copy of the reference to the same array shelf points at, so writing stock[1] = 0 changes the shared array and main sees the zero. Had markSold written stock = new int[3] instead, only its own copy of the reference would have changed.

What a method receives

Argument typeThe parameter holdsCan the method change the caller's data?
primitive (int, double, boolean, ...)a copy of the valueno
array or object referencea copy of the referenceyes, through the reference: elements and fields
anya new local variablereassigning the parameter never affects the caller

Common mistakes

  • A path with no return

    Why it goes wrong: static int sign(int n) { if (n > 0) { return 1; } } fails with missing return statement: when n is not positive the method would end without a value.

    Fix: Return on every path, typically by ending with an unconditional return.

     Java · fix
    static int sign(int n) {
        if (n > 0) {
            return 1;
        }
        return 0;
    }
  • Calling a non-static method from main

    Why it goes wrong: A method declared without static belongs to an object. Calling it from main gives non-static method greet() cannot be referenced from a static context, because no object exists yet.

    Fix: Mark helper methods static while everything lives in Main; create an object first once you move to classes.

     Java · fix
    static void greet() {
        System.out.println("hello");
    }
  • Expecting a method to change a primitive argument

    Why it goes wrong: static void doubleIt(int n) { n *= 2; } changes only its local copy; the caller's variable keeps its value.

    Fix: Return the new value and assign it at the call site.

     Java · fix
    static int doubled(int n) {
        return n * 2;
    }
    // caller:
    count = doubled(count);
  • Overloading on the return type only

    Why it goes wrong: static int f(int a) and static double f(int a) together fail with method f(int) is already defined; the parameter lists are identical, so a call f(3) could not be resolved.

    Fix: Give the methods different parameter lists or different names.

Where you use this

A grading program reads a set of marks, computes their average and prints a grade letter. Written as one long main, the three jobs blur together and none can be checked separately. Split into readMarks, average and gradeFor, each method has one purpose, main reads as the outline of the program, and the grade rule can be tested by calling gradeFor(72) directly. Methods also remove duplication: a bug fixed in gradeFor is fixed for every caller at once.

 Java · in practice
public static void main(String[] args) {
    int[] marks = readMarks();
    double avg = average(marks);
    System.out.println("Average " + avg + ", grade " + gradeFor(avg));
}

static String gradeFor(double avg) {
    if (avg >= 70) {
        return "A";
    }
    if (avg >= 50) {
        return "B";
    }
    return "C";
}

Key points

  • A method is declared as modifiers, return type, name, parameter list and body; void means no result.
  • return ends the method and supplies the value; every path of a non-void method must return.
  • Arguments are passed by value: primitives are copied, references are copied, so array elements can be changed but the caller's variable cannot be reassigned.
  • Overloads share a name and differ in parameter types or count, never only in return type.
  • Parameters and variables declared inside a method are local to that call.
  • Helpers called from main must be static until you work with objects.
  • Name methods as verb phrases that say what they do: parcelCost, isValidPin, printLabel.

Try it yourself

Complete the cube method so that it returns its argument multiplied by itself three times. The calls in main should then print 27 and 1000.

Your program
public class Main {
    static int cube(int n) {
        return 0;   // replace this
    }

    public static void main(String[] args) {
        System.out.println(cube(3));
        System.out.println(cube(10));
    }
}
Expected output: 27 1000

Practise this

Exercises for this lesson are in the Java practice set.

Open the Java playground

Frequently asked questions

Is Java pass by value or pass by reference?

Pass by value, always. The method's parameter is a fresh variable initialised with a copy of the argument. For a primitive that is a copy of the number. For an object the argument is a reference, so the copy points at the same object, which is why a method can change an array's elements; but assigning the parameter to a new object does not touch the caller's variable, which is the test that distinguishes it from true pass by reference.

Can a Java method return more than one value?

Not directly; a method has one return type. To hand back several values, return an array, a small object or a record (Java 16 and later, covered in the records lesson). Returning a record such as record Stats(int min, int max) {} is the clearest option because each value keeps its name.

Progress is stored only in this browser.

How this page was checked. Every program on it was run with OpenJDK 21 at build time by the publishing checks, and the output shown is what it printed. Running Java inside the browser is not available yet, so the Run button is absent rather than pretending; copy the code and run it with OpenJDK 21 locally.