Source: CS61B Textbook — 10.4 Higher-Order Functions in Java

key words: functional interface, apply, higher-order functions, function pointers, lambda, method reference

1. The Core Problem: Java 7 Has No Function Pointers

In Python, a function is a first-class value — you can store it in a variable and pass it straight into a higher-order function (HoF):

def tenX(x):
    return 10 * x

def do_twice(f, x):
    return f(f(x))

do_twice(tenX, 2)   # pass the function itself

In Old School Java (7 and earlier) this is impossible. As the textbook puts it: "Memory boxes (variables) cannot contain pointers to functions." A variable can hold an int, or a reference to an object — but never a reference to a bare function. So there's no way to write do_twice(tenX, 2) directly.

2. The Workaround: An Interface Pretending to Be a Function

If we can't put a function in a variable, we put an object in a variable instead — an object whose whole job is "be callable." We define an interface to serve as the type of that object:

public interface IntUnaryFunction {
    int apply(int x);
}

public class TenX implements IntUnaryFunction {
    public int apply(int x) {
        return 10 * x;
    }
}

The interface is a function's stand-in: TenX is no longer "the function tenX," it's "an object that knows how to apply."

Analogy: you can't mail a verb. So you mail a little robot whose only button is labeled apply — pressing the button does the verb. The interface is the spec for "has an apply button."

3. Why int apply(int x); Is Necessary — Two Jobs

This is the crux. The single line int apply(int x); inside the interface is doing two things at once:

Job What it guarantees
(a) Makes the object callable The HoF holds an IntUnaryFunction reference; the compiler only allows f.apply(x) if apply is declared on that type
(b) Forces implementers to supply it apply is abstract, so any class that implements IntUnaryFunction (like TenX) must override it — every such object really is callable

Here is the HoF that consumes it:

public static int do_twice(IntUnaryFunction f, int x) {
    return f.apply(f.apply(x));
}

do_twice receives an IntUnaryFunction reference f. To actually run the wrapped behavior, it calls f.apply(x). The compiler permits this only because apply is declared in the interface. Delete int apply(int x); and the interface becomes empty — f.apply(x) no longer compiles, because the compiler has no evidence the type IntUnaryFunction has any such method.

⚠️ Common misconception to flag: "apply is a variable that gets assigned the function." No. apply is not a variable — it's an abstract method declaration. The thing playing the role of "function object" is the instance (new TenX()), not the method name. The variable in the HoF story is f, not apply.

Distilled rule: the interface is a function pointer's replacement; for the replacement to be usable it must expose one callable method with a known signature — and int apply(int x); is that contract.

4. Later Java (8+): Same Mechanism, Shorter Syntax