Today we'll learn how to package up our code into reusable pieces called functions.
Along with implementing new algorithms and exploring new data structures, we'll also explore new ways of structuring our programs in future lessons. Functions—also called methods or subroutines—are the basic structural building blocks of computer programs.
Important note: we're charging forward in our exploration of Java. Functions are such an important idea that it's worth getting a bit ahead of ourselves. Starting tomorrow we're going to slow down, practice what we've already learned, and integrate. Put another way: tomorrow's lesson is shorter!
Let's return to the search algorithm that we presented in the last lesson:
This is a nice example of solving one specific problem: search for the value contained in
lookingFor in the array
But what if I wanted to also look for another value in a second array?
I could do this:
This works fine. But there's a problem: we have duplicated our algorithm now in two places! We could do this, and continue copy-and-pasting our search algorithm wherever we needed it in our code. But a better strategy is to refactor our code so that we can reuse the algorithm in multiple places.
In computer programming, a subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed.
Now let's consider how to convert the code for our search algorithm into a function.
To make this code reusable, our goal is to rewrite it so that it can look for any
int value in any array of
To do this, we need to separate the algorithm that can be reused from the inputs that can vary.
Let's walk through how to do that:
The walkthrough above identified two of the required parts of a function. First, we need the code that we're going to reuse. Second, we need to identify the data or inputs that are provided to that code.
There are two additional requirements. Third, each function needs a name so that we can identify it when it is reused. Fourth, functions need some way of returning a result—in our example, whether or not the value was found or not.
These set of requirements lead us to our first function definition. Let's go through each part of it carefully together:
We call executing the reusable logic that a function encapsulates calling that function. To call a function, we need to identify it using its name and provide the inputs that it needs to complete the task. Let's go through calling our search function and several different ways that we can use the result:
Part of how we make functions reusable is by having them accept arguments. For example, this function does implement a search, but it's not particularly useful:
In this case
searchArrayForFour is a perfectly valid algorithm for search an array, but only for the value 4.
What if we want to search for 5, or 8?
We don't want to have to write a separate search function for each value we might want to look for!
Instead, as we see above, we let the value that we are looking for be a parameter that is provided to the function by the caller. This allows us to search for any value, not just a specific value. In the walkthrough below we talk a bit more about function arguments and compare them to the variable declaration and initialization we've seen previously.
returnand Return Type
Our new bit of Java syntax in this lesson is the
return causes a function to immediately stop and return or yield a value:
return value must match the return type of the method, which is part of the method declaration.
And every function must return a value of the type declared.
For example, this doesn't work:
We'll continue using
System.out.println to trace the execution of our programs as they run.
But it's important to note that this is not returning a value: