Saltar a contenido

04 - Methods

What this session is

About 45 minutes. You'll learn how to define your own methods (Java's word for functions), use static, return values, and pass parameters. By the end you can break programs into named pieces.

"Method" vs "function"

Other languages call them functions. Java calls them methods because they always live inside a class. That's the only difference in vocabulary - the concept is the same: a named, reusable block of code that takes input and (usually) returns output.

The shape

public static returnType name(parameters) {
    // body
    return something;
}

Concrete example:

public class Math1 {
    public static int doubleIt(int x) {
        return x * 2;
    }

    public static void main(String[] args) {
        System.out.println(doubleIt(5));   // 10
        System.out.println(doubleIt(7));   // 14
    }
}

Walk through doubleIt:

  • public - visible from outside the class.
  • static - belongs to the class itself, not to any object. (We'll explain static properly when we meet objects in page 05. For now: methods in a main-only program need to be static so main can call them.)
  • int - the return type.
  • doubleIt(int x) - name and parameter list.
  • return x * 2; - compute and send back.

Compile and run:

javac Math1.java && java Math1

Output: 10, 14.

Multiple parameters

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

Parameters are separated by commas. Each gets its own type.

Methods that return nothing

void means "this method returns nothing":

public static void sayHi(String name) {
    System.out.println("Hi, " + name);
}

public static void main(String[] args) {
    sayHi("Alice");
    sayHi("Bob");
}

No return line. The method runs for its side effect (printing).

Methods calling methods

Methods can call other methods (including the same class's):

public class Math2 {
    public static int square(int x) {
        return x * x;
    }

    public static int sumOfSquares(int a, int b) {
        return square(a) + square(b);
    }

    public static void main(String[] args) {
        System.out.println(sumOfSquares(3, 4));   // 9 + 16 = 25
    }
}

Composition - small named pieces combined.

Method overloading: multiple methods, same name, different parameters

Java lets you define several methods with the same name as long as their parameter lists differ:

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

The compiler picks the right one based on the argument types at the call site. Useful for variants of an operation on different types.

Common overload: println itself is overloaded for every type - that's why System.out.println(42) and System.out.println("hello") both work.

Default arguments - Java doesn't have them

Languages like Python have default parameters: def greet(name, greeting="hello"). Java doesn't.

The Java way: overload methods.

public static String greet(String name) {
    return greet(name, "hello");
}
public static String greet(String name, String greeting) {
    return greeting + ", " + name;
}

One method delegates to the more-general one with a default. The IDE and the compiler give you the same affordance via overloads.

Variable scope

Variables created inside a method exist only inside that method:

public static int doubleIt(int x) {
    int result = x * 2;
    return result;
}

public static void main(String[] args) {
    System.out.println(result);   // ERROR - `result` doesn't exist here
}

Each method has its own world. Pass values in via parameters; get values out via return.

Local variables, parameters, and final

Inside a method you can mark variables final, meaning "this can't be reassigned after its first value":

public static int doubleIt(int x) {
    final int multiplier = 2;
    // multiplier = 3;   // ERROR - can't reassign a final
    return x * multiplier;
}

Useful for "this constant won't change." Increasingly, modern Java code marks variables final by default unless they need to change - the discipline forces you to think about mutation.

var for local variables (modern Java)

You met var in page 02 for inferred types. Same rule for locals declared from a method call:

public static void main(String[] args) {
    var sum = add(3, 4);            // Java infers int
    var greeting = greet("Alice");  // Java infers String
    System.out.println(sum);
    System.out.println(greeting);
}

var for locals; explicit types for everything else.

Why methods matter

  1. Naming. doubleIt(7) reads better than re-typing 7 * 2 everywhere, especially when the operation is more complex.
  2. Reuse. Write once, call many times.
  3. Testing. You can test doubleIt separately from the rest (page 10).
  4. Structure. Reading a 500-line main is awful. Reading 20 small named methods tells you what the program does at a glance.

These benefits compound. They're invisible at 30 lines and decisive at 300.

Exercise

In a new file IsEven.java:

  1. Write a method isEven(int n) returning boolean. Use the % operator.

  2. From main, print isEven(4) and isEven(7). You should see true and false.

  3. Write a method countEvens(int max) returning int that counts even numbers in 1..max. Use a for loop and call isEven.

  4. Print countEvens(10). Expected: 5.

  5. Print countEvens(100). Expected: 50.

  6. Stretch: add overloaded countEvens(int min, int max) that counts evens in min..max. Test with countEvens(5, 15) (expected: 6).

What you might wonder

"Why static? When do I use non-static?" static means "belongs to the class." Non-static means "belongs to an instance" (object). You'll meet instance methods in page 05. For now, in a single-file program with only main, all your helper methods are static - they have to be, so main (which is static) can call them.

"Java doesn't have first-class functions?" It does - but they're called lambdas and method references, and they were added in Java 8. We'll meet them when we need them (page 06 with collections, page 08 with pattern matching).

"What if I forget return in a non-void method?" The compiler refuses to build. "Missing return statement." Read the error; fix the path that's missing one.

"Can a method modify its parameter?" For primitives: the parameter is a copy; modifying it doesn't affect the caller. For objects: the parameter holds a reference to the same object; modifying the object's fields does affect the caller (more in page 05).

Done

You can now: - Define methods with parameters and return types. - Use void for methods that don't return. - Overload methods (same name, different parameters). - Use var for inferred local types. - Use final to mark locals as non-reassignable. - Understand why static/non-static matters (preview).

Next page: classes and objects - where Java's everything-is-a-class design really kicks in.

Next: Classes and objects →

Comments