Java Method

June 27, 20265 min readUpdated 8/20/2026

A method is a named block of code that takes inputs and optionally produces a result. Methods are how you stop repeating yourself and how you break a large problem into pieces small enough to understand one at a time.

Anatomy

public int add(int a, int b) {
    return a + b;
}
  • public — who can call it. Packages covers the four options.
  • int — the return type. The type of the value it hands back.
  • add — the name. A verb, in camelCase.
  • (int a, int b) — the parameters, the inputs it needs.
  • return a + b; — produces the result and exits immediately.

A method that does something rather than computing something has the return type void, and either omits return or uses a bare return; to exit early:

public void printGreeting(String name) {
    if (name == null) {
        return;                          // leave now, produce nothing
    }
    System.out.println("Hello, " + name);
}

The compiler will not let a non-void method finish without returning something on every path, which catches a real class of mistake:

public String describe(int score) {
    if (score > 50) {
        return "pass";
    }
    return "fail";                       // remove this line and it will not compile
}

Calling a method

public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }

    public static int square(int n) {    // static — no object needed
        return n * n;
    }
}

class Demo {
    void run() {
        Calculator calc = new Calculator();
        int sum = calc.add(2, 3);        // instance method: needs an object
        int sq = Calculator.square(4);   // static method: called on the class

        System.out.println(sum + " " + sq);   // 5 16
    }
}

The distinction is about whether the method needs the object's data. square works entirely from its argument, so it does not need an instance and should be static. A method that reads or changes fields must be an instance method.

Pass by value — including for objects

This is the part of methods that genuinely confuses people, and the confusion comes from a half-true summary. Java is always pass-by-value. What gets copied for an object is the reference, not the object.

void changeNumber(int n) {
    n = 99;                              // changes the local copy only
}

void changeArray(int[] arr) {
    arr[0] = 99;                         // follows the reference — the caller sees this
}

void replaceArray(int[] arr) {
    arr = new int[]{99};                 // repoints the local copy — the caller sees nothing
}

void demo() {
    int number = 1;
    changeNumber(number);
    System.out.println(number);          // 1  — unchanged

    int[] data = {1, 2, 3};
    changeArray(data);
    System.out.println(data[0]);         // 99 — the array itself was modified

    int[] other = {1, 2, 3};
    replaceArray(other);
    System.out.println(other[0]);        // 1  — still the original array
}

Compare the last two. changeArray modifies the object the reference points at, which the caller shares. replaceArray assigns a new reference to its own parameter variable, which the caller never sees. Both are "pass by value" — the value copied is the reference.

The practical consequence: a method that takes a mutable object can change the caller's data, and you should say so in the name. sortInPlace(list) is honest; process(list) that quietly reorders it is not.

Overloading

Several methods can share a name if their parameter lists differ:

public class Printer {
    void print(String s) { System.out.println("text: " + s); }
    void print(int n) { System.out.println("number: " + n); }
    void print(int a, int b) { System.out.println("two: " + a + "," + b); }
}

The compiler picks the overload by the argument types, at compile time. The return type is not part of the signature — two methods differing only by return type will not compile.

Overloading is useful for genuine convenience variants. It becomes a trap when the overloads do different things, or when the compiler's choice is not the obvious one:

List<Integer> list = new ArrayList<>(List.of(10, 20, 30));

list.remove(1);                          // remove(int index) -> removes 20
System.out.println(list);                // [10, 30]

list.remove(Integer.valueOf(30));        // remove(Object) -> removes the VALUE 30
System.out.println(list);                // [10]

That is a real trap in the standard library, and it is worth seeing once so it does not cost you an afternoon.

Varargs

int sum(int... numbers) {                // zero or more ints
    int total = 0;
    for (int n : numbers) {
        total += n;
    }
    return total;
}

void demo() {
    System.out.println(sum());            // 0
    System.out.println(sum(1, 2, 3));     // 6
    System.out.println(sum(new int[]{1, 2}));  // 3 — an array works too
}

Inside the method, numbers is an ordinary array. There can be only one varargs parameter and it must be last.

A method that calls itself

Recursion is legal and occasionally the clearest expression of a problem that is defined in terms of itself. It needs two things: a base case that returns without recursing, and a step that moves toward it.

long factorial(int n) {
    if (n <= 1) return 1;            // base case — without this it never stops
    return n * factorial(n - 1);     // each call is closer to the base case
}

void demo() {
    System.out.println(factorial(5));   // 120
}

Every call occupies a frame on the call stack, so a recursion that goes too deep — or one whose base case is never reached — ends in StackOverflowError. For anything that might run thousands deep, write a loop. Recursion earns its place on genuinely nested data such as trees and directory listings, not on counting.

Writing methods worth reading

  • One job each. If the name needs an "and", it is two methods.
  • Name it after what it produces, not how. calculateTotal, not doTheMath. A boolean method reads as a question: isValid, hasExpired.
  • Few parameters. Past three, the call site becomes a puzzle of positional arguments. Group them into an object instead.
  • Keep it short. There is no magic number, but a method you have to scroll is usually several methods that have not been separated yet.
  • Return early. Guard clauses at the top, the real work unindented below.

Next

Methods and fields belong to classes, which you have been writing without explanation. Classes is next.