Methods in Java: Declaration, Parameters, Return Types

A method in Java is a named block of code that performs a task, optionally accepting parameters and returning a value. Methods are the basic unit of code reuse in object-oriented programming.

Basic method declaration

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

// Usage
Calculator c = new Calculator();
int sum = c.add(2, 3); // 5

A method has four parts: access modifier, return type, name, and parameter list.

Return types

Every method declares what it returns. Use void if it returns nothing:

public void log(String message) {
    System.out.println("[LOG] " + message);
}

public double average(double a, double b) {
    return (a + b) / 2;
}

public String greeting(String name) {
    return "Hello, " + name;
}

A non-void method must return on every possible code path, or the compiler rejects it.

Parameters

// Fixed arity
public int multiply(int a, int b) { return a * b; }

// Variable arity (varargs)
public int sum(int... numbers) {
    int total = 0;
    for (int n : numbers) total += n;
    return total;
}
sum(1, 2, 3, 4); // 10

// Default values? Not in Java β€” use overloading (see below)

Parameters are passed by value. For objects, the value is the reference β€” so the method can mutate the object but cannot replace the caller's variable.

Static vs instance methods

public class MathUtil {
    // Static β€” no object needed, called on the class
    public static int square(int n) { return n * n; }

    // Instance β€” requires an object
    public int increment(int n) { return n + 1; }
}

// Static call
int s = MathUtil.square(5);

// Instance call
MathUtil m = new MathUtil();
int i = m.increment(5);

Use static when the method doesn't depend on any instance state β€” utility functions, factory methods, constants.

Access modifiers

ModifierVisible from
publicanywhere
protectedsame package + subclasses
(none)same package only (package-private)
privatethe declaring class only

Prefer the strictest level that works. Most helper methods should be private; only the public API should be public.

Method overloading

Multiple methods can share a name if they differ in parameter list. The compiler picks the right one based on the arguments.

public class Printer {
    public void print(int n)      { System.out.println("int: "    + n); }
    public void print(double d)   { System.out.println("double: " + d); }
    public void print(String s)   { System.out.println("string: " + s); }
    public void print(String s, int times) {
        for (int i = 0; i < times; i++) print(s);
    }
}

Overloading also replaces default parameter values, which Java doesn't support natively.

Method overriding

A subclass can override a method to change its behavior. Always annotate with @Override β€” the compiler then verifies the signature matches.

public class Animal {
    public String sound() { return "..."; }
}

public class Dog extends Animal {
    @Override
    public String sound() { return "Woof"; }
}

this

Inside an instance method, this refers to the current object. Useful to disambiguate parameters from fields:

public class User {
    private String name;

    public void setName(String name) {
        this.name = name; // 'this.' distinguishes the field from the parameter
    }
}

Main method

The entry point of a Java program has a fixed signature:

public static void main(String[] args) {
    System.out.println("Hello");
}

Since Java 21 (JEP 445), an unnamed class with a top-level void main() is also valid, but older setups still need the classic signature.

Returning multiple values

Java has no tuple type. Use:

  • A record (Java 16+): public record Result(int min, int max) {}
  • A small dedicated class
  • An array or list (loses type safety)
  • A Map<String, Object> (avoid β€” stringly typed)
public record Stats(int min, int max, double avg) {}

public static Stats analyze(int[] data) {
    int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE, sum = 0;
    for (int n : data) {
        min = Math.min(min, n);
        max = Math.max(max, n);
        sum += n;
    }
    return new Stats(min, max, (double) sum / data.length);
}

Best practices

  1. Short and focused β€” if a method spans more than 30 lines, split it.
  2. Verb names β€” getUser(), computeTotal(), sendEmail().
  3. Limit parameters β€” more than 3 or 4 is a code smell; group related ones into an object.
  4. Return defensive copies for mutable collections, not the internal field.
  5. Validate early β€” reject invalid arguments with IllegalArgumentException at the top of the method.
  6. Favor immutability β€” fewer side effects, easier to reason about.

Methods are the verbs of Java. A well-designed method does one thing, is named accordingly, and is short enough to read at a glance.