Concepts / Functional Interfaces

Functional Interfaces

A functional interface is an interface with a single abstract method, and the source uses it to represent a single method.

  • Programming

Why a Call Needs a Specification

Imagine you want to call a subroutine that someone else wrote. Before you write the call, you have to answer a few questions. What is the subroutine called? How many values does it expect you to pass in, and what type is each one? What type of value does it send back? If any of these answers is wrong, the call cannot be made correctly. The information that answers these questions is the subroutine's specification.

A functional interface is one way to write that specification down in a Java file. It is a file that holds a specification for exactly one subroutine, and it is defined in a .java file just as a class is. This article works through two short functional interface declarations taken from a Java source. Your goal is to learn what makes an interface count as functional, how to read its declaration, and how to check a use of the subroutine against the declaration.

Two Checks for a Functional Interface

Definition

A functional interface is an interface with a single abstract method. The source uses it to represent a single method.

The definition has two parts, and you should check them separately. The first check is that the type is an interface. A declaration that begins with the word interface, rather than class, passes this check. The second check is that the interface contains exactly one abstract method. Counting the methods inside the braces is how you apply it. If there is exactly one method, the declaration passes the second check.

Reading the FunctionR2R Declaration

The first example in the source is a whole functional interface squeezed onto one line. It is saved in a file named FunctionR2R.java, which matches the name of the interface, as with any Java class. The declaration reads as follows.

java
Notes on the code
  • public makes the interface visible
  • interface marks this as an interface, not a class
  • FunctionR2R is the interface name
  • double before valueAt is the return type
  • valueAt is the method name
  • double x is the single parameter

Read the declaration from left to right. The word public makes the interface visible, and the word interface tells you this is an interface rather than a class. FunctionR2R is the interface name. Inside the braces there is one line that names a subroutine, valueAt. The first word before the method name is the return type, which here is double, so the subroutine gives back a double. The items inside the parentheses are the parameters. Here there is one parameter, of type double, named x. Put together, the declaration says: there is a subroutine called valueAt, it takes one double, and it returns a double. The source describes FunctionR2R as a functional interface representing a function that takes a double and returns a double.

The parameter name x is written in the declaration, but it is not really part of the specification. What matters to a caller is how many parameters there are and what type each one has. The name is a label that helps a reader, and it does not change what a valid call looks like.

Predicting What the File Contains

Before you look at the file's contents, make a prediction. Look at the one-line declaration again and ask yourself how much of the file is about how valueAt actually computes its answer, and how much is only about the shape of the call. Commit to an answer before you read the next block.

What do you think happens?

Does the FunctionR2R file contain any computation for how valueAt calculates its result?

  • Yes, the computation is written inside the braces

  • No, the file only states the shape of the call: name, parameter, and return type

Reveal answer
Answer:

No, the file only states the shape of the call: name, parameter, and return type

The declaration ends with a semicolon after the parameter list. It has no method body, no fields, and no implementation logic. Inside the braces there is only the single line that names the subroutine and gives its parameter and return type. A computation would appear inside the braces if it were present, and it is not there.

Your prediction is checked by reading the declaration itself. The trace attached to this lesson runs the real Java declaration so you can watch the structure as it is read. If the file did contain computation, you would expect to find it inside the braces. You do not find it there, so the file records a specification and nothing more.

ArrayProcessor and the Void Return

The source gives a second example with a different shape. It describes a subroutine that does not return anything and takes two parameters, an array of strings and an int. The source does not name the array parameter in the excerpt, so this article uses items as an illustrative name. The declaration is shown below.

java
Notes on the code
  • ArrayProcessor is the interface name
  • void is the return type: no value comes back
  • process is the method name
  • String[] items is an array of strings
  • int count tells the processor how many entries to work with

The two declarations share one structure even though their contents differ. Each one names a single subroutine and then states its parameters and its return type. The difference is in the types. The return type of ArrayProcessor is void, which means the process method does not hand a value back to the caller. A void return type is still a return type, and it tells the caller that no value comes back. The count parameter tells the processor how many entries to work with, which contrasts with FunctionR2R, where the single input is one double.

FeatureFunctionR2RArrayProcessor
Method namevalueAtprocess
ParametersOne double, named xA String array and an int named count
Return typedouble (gives back a value)void (gives back nothing)
Source's descriptionA function that takes a double and returns a doubleA processor that operates on an array of strings

The two functional interfaces differ in what they accept and what they return.

The Three Facts a Specification Records

The specification records three facts about one subroutine. The first is the subroutine's name. The second is its parameters, meaning how many there are and their types. The third is its return type. Each fact has a fixed place in the declaration. In FunctionR2R, the name is valueAt, the parameter is one double, and the return type is double. In ArrayProcessor, the name is process, the parameters are a String array and an int, and the return type is void.

The word one matters here. A single functional interface is about a single subroutine. If you need to describe two different subroutines, you write two interfaces. This is what the source means when it describes the interface as a specification for a single subroutine.

  1. 1
    Find the method name: the identifier immediately before the opening parenthesis.
  2. 2
    Find the return type: the word immediately before the method name.
  3. 3
    Find the parameters: the items inside the parentheses, counted and typed one by one.
  4. 4
    Check that the declaration contains exactly one method inside the braces.

Finding Where a Call Diverges

Once you know the three facts, you can debug a broken use of a subroutine by asking where the use departs from the specification. You do not need to guess. You compare the call against the declaration line by line, starting with the name, then the parameters, then the return type.

Worked example

Locating a mismatch in a call to valueAt

Some code calls valueAt with two numbers, valueAt(3.0, 4.0), instead of one. Where does the call stop matching the specification?

  1. 1
    Read the specification

    FunctionR2R declares valueAt with one double parameter and a double return type.

  2. 2
    Check the name

    The call uses valueAt, which matches the declared method name. The name is not the problem.

  3. 3
    Check the parameter count

    The call passes two arguments, but the specification says there is one double parameter. The mismatch is here.

  4. 4
    Check the return type

    The return type cannot be judged from this call alone, but the parameter count already shows the call is wrong.

Result

The call diverges at the parameter list. The specification expects one double, and the call supplies two.

The before-and-after pair shows the fix. The first call passes two numbers, so it diverges from the one-double parameter list. The corrected call passes a single double, which matches the declaration. The return type is unchanged by this fix because the declaration already says the method returns a double.

Mistakes When Reading Signatures

  • Common mistake

    Treating the parameter name as part of the contract

    What it looks like

    Believing that a call must use the name x in order to match the declaration.

    Why it fails

    The parameter name is written in the declaration, but the caller is judged by the number and types of parameters.

    Do this instead

    Compare parameter counts and types when checking a use.

  • Common mistake

    Reading the return type as the method name

    What it looks like

    Thinking that double in public interface FunctionR2R { double valueAt(double x); } is the name of the method.

    Why it fails

    The word before the method name is the return type. The method name is the identifier that comes directly before the parentheses.

    Do this instead

    Locate the name by finding the identifier right before the opening parenthesis.

  • Common mistake

    Assuming void means the method is missing a return type

    What it looks like

    Thinking the ArrayProcessor declaration is incomplete because it has no value after the word void.

    Why it fails

    A void return type is still a return type. It tells the caller that no value comes back.

    Do this instead

    Read void as the declared answer: the subroutine returns nothing.

  • Common mistake

    Expecting computation inside a functional interface file

    What it looks like

    Looking in the FunctionR2R braces for the arithmetic that valueAt performs.

    Why it fails

    A functional interface records a specification. The declaration has one method with no body, so it does not show how the work is done.

    Do this instead

    Expect the file to contain only the shape of the subroutine: name, parameters, and return type.

Checking Your Reading

EASY

Read the declaration public interface ArrayProcessor { void process(String[] items, int count); } and answer three questions. What is the method name? How many parameters does it take, and what are their types? What is the return type, and what does it tell the caller?

Hints
  • The method name is the identifier directly before the opening parenthesis.
  • Count the items inside the parentheses, separated by commas.
  • The word immediately before the method name is the return type, and void means no value comes back.
MEDIUM

A caller writes a call to process with only one argument, process(names). Using the ArrayProcessor declaration, state at which step the call diverges from the specification and explain why.

Hints
  • Compare the number of arguments in the call with the number of parameters in the declaration.
  • Ask whether the name and return type are also affected.

Key Takeaways

  • A functional interface is an interface with a single abstract method, and it is a Java file that holds a specification for exactly one subroutine.
  • Read a declaration from left to right: the word before the method name is the return type, the identifier before the parentheses is the method name, and the items inside the parentheses are the parameters.
  • The specification records three facts about one subroutine: its name, its parameters (how many and their types), and its return type. The parameter name is not part of the specification.
  • FunctionR2R takes one double and returns a double, while ArrayProcessor takes a String array and an int and returns void.
  • A call that goes wrong can be located by comparing it against the specification fact by fact, starting with the parameter list.