Java 211
Methods
Yosef Mendelsohn
Methods
It is surely no surprise to you that computer programs can be very long and complex. For this reason, there are many ways of organizing programs. One of the key ways to organize a program is to divide it into specific tasks. Every task (and often, individual parts of a given task) may be included in its own little section called a method. (Some people and programming languages will also call them functions. There are subtle distinctions, but we won’t worry about them here. For now, you may hear me use the terms interchangably).
Methods have another valuable use: They are a great way to allow you to repeat code over and over again. For example, suppose you find that in a program you want to ask the user for a number and then determine the square root of that number. Suppose also that you will want to do this over and over again in your program. This is a great time to use a method. In other words, whenever you want to do this little bit of functionality, you don’t have to go back and re-type (or copy-paste) the code into your program. You can simply “invoke” (i.e. give the order to execute) the method that you have already written.
Don’t confuse methods with loops. A loop repeats code over and over again, but only at the current spot in the program. A method allows your to repeat code, but at any point in the program. You might invoke a method at line 25 in your program, and then invoke the same method at line 2500.
A method is a collection of programming statements that is given a specific name. When you “invoke” a method (by giving its name), you are transferring the flow of control to that group of statements. When the method has completed, flow returns to the location from which the method was called.
Pre-Defined Methods
Are methods that have been pre-created for us by the people who created Java. For example, the length() method used with String objects is a pre-defined method. So are all of those methods seen in the String API. Let’s look at a few of those methods now:
String s = “Hello DePaul!”;
System.out.println( s.charAt(0) ); //outputs an ‘H’
System.out.println( s.charAt(12) ); //outputs a ‘!’
System.out.println( s.charAt(13) ); //error – there is no 13th index!
System.out.println( s. charAt (s.length()-1) ); //okay too!
String s1 = “Hello DePaul!”;
String s2 = “Hello DePaul!”;
if ( s1.equals(s2) ) //returns true
if ( s1.equals(“Hello DePaul!”)) //also returns true
If you look at a class called ‘Math’, you will see numerous pre-defined methods that are available to us for basic mathematical functionality.
For example, to calculate a square root, there is a method called ‘sqrt’ that accepts any numeric data-type and returns it’s square root. Here is the “header” of that method:
static double sqrt (double a)
This tells you that the method accepts one argument of type double. By reading the information in the API you can also see that the method returns a double corresponding to the square root of ‘a’.
Therefore, you should be able to invoke the method by typing something like:
double x = sqrt(9.0); //x will be set to 3.0
Right? Actually, WRONG!
The problem is one of context. Consider where you would see this line of code:
public class Test
{
public static void main (String[] args)
{
double x = sqrt(3.0); //will give a ‘No such method’ error
System.out.println(x);
}
}
Using our favorite algorithm we say: “The system looks for a method called ‘sqrt’ that accepts ‘1’ argument(s) of type ‘double’.” Will it find such a method?
No… Why? Because the method lives in a completely different class.
In other words, we somehow need to indicate to the system to look for the ‘sqrt’ method in the Math class. How do we do this? By typing: Math.sqrt(…)//note the dot!
By changing the line to read:
double x = Math.sqrt(9.0);
we tell the system where to go to look for the sqrt method.
Note: This method of invoking methods (ie: preceding the method name by the class name) will NOT work for all methods. It will only work for methods that have the word ‘static’ in their signature. For now, then, you should put the word static before all of your methods because they are meant to be stand alone. (You will understand more about ‘stand alone’ methods when we discuss classes in more detail).
User-Defined Methods
Comments: All methods must have a comment at the top detailing what the method will do. This will keep you focused on exactly what it is the method is supposed to accomplish. Methods generally have one and only one very specific task to do.
Here is the outline of a very basic method that outputs a simple greeting to the screen. (Note the comment at the beginning of the method).
//output a generic greeting to the screen
public static void printGreeting()
{
System.out.println("Hi, welcome to the printGreeting function!");
System.out.println("Hello Miss/Sir, how are you today?");
} //end of printGreeting method
Now at any point in your program (e.g. from somewhere in your main() method, this method can be invoked by simply typing:
printGreeting();
ALWAYS WRITE YOUR COMMENT FIRST. THEN WRITE THE METHOD.
This last instruction WILL save you time in the long run. I promise. One key to writing a method is being VERY explicit about what you want the method to do.
Another simple example:
//output the sum of two numbers to the screen
//the numbers have been hard-coded with values
public static void outputTheSum()
{
int num1 = 10;
int num2 = 22;
System.out.println("The sum of the numbers is " + (num1+num2) );
} //end of outputTheSum method
Parameters (Arguments)
When creating a method, it is sometimes required to provide the method with parameters.
(Parameters should not be confused with “arguments” – more on this later).
For example, suppose you wanted to create a version of the greeting method earlier, but one that personalizes the greeting based on the user’s name.
//Outputs a personalized greeting to the screen.
//This method requires that a String representing the
//user’s name be provided as an argument
//when the method is invoked.
public static void printGreeting(String name)
{
System.out.println("Hi, welcome to the printGreeting function!");
System.out.println("Hello " + name + ", how are you today?");
} //end of printGreeting method
When we created the above method, we decided to include a parameter. This means that in order to invoke this method, it is not enough to simply write the method’s name. For example, trying to invoke the method by typing: printGreeting(); will not work. This is because this particular method has one parameter. What this means is that in order to invoke the method, you must
- Write the method’s name
- Provide the method with one argument (of the proper type!)
So, to invoke this method, you must type:
printGreeting(“Bob”); or
printGreeting(“Erin Brokovitch”);
Again: The above method takes one argument. When you call the method, you must pass it one argument of type ‘String’.
Note that passing an argument of a different type will produce an error.
Memorize and use the following statement to answer the questions that follow:
The system looks for a method called ______that accepts ____ argument(s) of type ______.
Given the method just above, what will take place with the following?
printGreeting(5)
printGreeting(Bob);
printGreeting(“Yosef Mendelsohn”);
printGreeting(“Bob”, 5);
Methods that Return a Value:
Methods can do an infinite number of things. Sometimes a method will output information to the screen, sometimes it may play sounds, it could enter information into a database, etc, etc, etc. Sometimes a method’s job is to return some information back to the computer program itself.
For example, suppose your program periodically needs to calculate the square of some number. You could write a method that accepts one argument, then calculates the square of that number, and then returns the resulting value back to the program. Here is how you might write such a method:
//calculates the value of number * number and returns it
public static int calcSquare (int number)
{
return (number * number);
} //end of method calcSquare
Here is the method in use:
int num, squareOfNumber;
System.out.print(“Please enter an integer number: “);
num = console.nextInt(); //assumes a Scanner object exists
squareOfNumber = calcSquare(num);
System.out.print(“The square of your number is: “ + squareOfNumber);
//Can you suggest a “shortcut” for the previous two lines?
Notice the highlighted line – let’s review what has happened: There are two operations on that line, an assignment (‘=’) and a method call. If you review your precedence table, you will see that method calls have higher precedence than assignments. So the method call is carried out first:
- The method call returns the value of ‘num’ squared.
- The value returned by the method is then assigned to the variable squareOfNumber
A useful way to think about this: When a method call returns a value, the method call (e.g. calcSquare(num) ) is essentially replaced by the value that was returned. So for example, from:
squareOfNumber = calcSquare(6);
We would get:
squareOfNumber = 36;
The Return Type:
public static int calcSquare (int number)
Look closely at the header of this last method. Notice that where we have usually written the word ‘void’ (e.g. in our main() methods), we instead see the word ‘int’. The word after public static tells you what data-type is returned by the method. In the case of our calcSquare() method, the data-type is an int.
Now look at our printGreeting method:
public static void printGreeting(String name)
If a method does not return a value, we simply put the word ‘void’ as the return type.
Terminology:
Let's go over some of the terminology of method definitions. You should become very familiar with these terms.
- The header refers to the first line of the method.
- A method is invoked by listing its identifier (i.e. its name) followed by the appropriate number of arguments. (The argument must, of course, be of the appropriate type). In the above example, the identifer is ‘square’ and the method requires one argument (of type ‘int’) .
- A formal parameter is the identifier that appears in the header of the method. The formal parameter is (are) a placeholder for the value of the argument.
- The method body describes how the method computes its value.
-A method consists of a method header and a body, much like the main part of the program does.
Return Statements:
If you are writing a method that returns a value, the method MUST have a return statement. If a method does not return a value (e.g. a method that has a return type of ‘void’), a return statement is optional.
The return statement ends the method: If a return statement is present, execution of that return statement automatically ends the method. In other words, there may be more code in the method after the return statement, but once a return statement is reached, the method is over. Flow then returns to the point in your program from where the method was invoked.
If the method returns a value, this value must be appended to the return statement.
Eg:
public static int calcSquare (int number)
{
return number*number;
}
In a void method, return statements are used to break out of a method. You will see examples of this later in the course.
One more example:
Let’s write a method that will accept two parameters of type ‘int’, and then return the sum of those two values. Here is the method definition:
//returns the average of num1 and num2
public static int sumTwoNumbers(int num1, int num2)
{
int theSum = num1 + num2;
return (theSum);
} //end of method sumTwoNumbers()
Can you suggest a shorter way of implementing this method?
Answer: leave out the variables and simply say: return (num1+num2);
‘void’ methods
As discussed earlier, some methods do not need to return a value. Consider a method that accepts one argument representing a person’s name, and a second argument representing an integer number ‘n’. The method then outputs the name ‘n’ times to the screen:
//outputs ‘name’ to the screen ‘n’ times
public static void printName(String name, int n)
{
for (int i=0; i<n; i++)
System.out.println(name);
} //end of printName method
Hopefully you’ll agree that no return value is needed from this method. In such cases, the return type of the method is indicated to be ‘void’. Note: This does not mean that ‘return’ is never needed in void methods. For example:
//prints inspirational message if ‘sales’ < 50000
public static void motivationalMessage(int sales)
{
if (sales < 50000)
return;
else
System.out.println(“Congratulations!!!”);
} //end of motivationalMessage method
-Remember, a ‘return’ immediately returns the flow of control to the location from where the method was originally called.
How Methods Get Invoked
When a method is invoked, Java looks for a method called ______that accepts ____ argument(s) of type ______.
Eg: printName(String name, int n)
“Java looks for a method called ‘printName’ that accepts 2 arguments of type String, then int.”
Being clear on this concept will help tremendously to understand our next topic:
Method Overloading:
It is possible and often very useful to have methods that have the same name. Think back to our printGreeting() earlier in the lecture. We begain by writing a version that was very generic and simply outputted a (very impersonal) greeting to the screen. We then decided to write a version of printGreeting that accepted one argument (of type String) and outputted a slightly more personal version of the greeting to the user.
Since these methods are extremely similar, we decided to give them the same name. Is this possible? Sure….
Well, if you have two methods with the exact same name, how does Java know which of the two methods you wish to invoke?
Answer: See the section above: “How Methods Get Invoked”…
The reason it works is that when invoking a method, Java not only looks at the identifier (name), it also looks at the number and type of arguments provided to the method. So if you invoke:
printGreeting();
Java will look for a method called printGreeting that accepts zero arguments. It will then invoke that particular version of printGreeting.
If instead, we invoked printGreeting and also provided an argument to the method of type String, Java will look for a method called printGreeting that accepts one argument of type String and will invoke that one. For example:
printGreeting(“Elizabeth”);
Question: What if we invoked printGreeting and passed the method one argument of type int? (e.g. printGreeting(23); )
Answer: It won’t work. Java will look for a method called printGreeting that accepts one argument of type int. When it doesn’t find it, it will give an error.
This ability to have multiple methods with the same name, and distinguished only by their signatures (identifier and number/types of arguments), is called method overloading. Method overloading is used A LOT in Java.
Comments
Note how all of the methods had a comment before them detailing what the method does. The comments preceding a method are the instruction manual for the method. These comments:
- explain what it is the method does
- warn the user of any limitations to the method (Eg: “//This method only works with arguments that are integers between 1 and 10”)
Put some thought into your comments. They are not there to make teacher haappy. They are there to ensure that you have a clear and specific goal for the method that you are about to write.
Abstraction (& Comments reiterated)
-Anyone who uses your method should not have to know anything about how the method does its work.
-For example, when you call a method, you don’t need to know anything about how the method works, you only need to know what it does. Eg: In “real life”, to drive a car, you need only know how to turn it on, turn it off, steer, break, and accelerate. You don’t need to know anything about how these things work, you need only know the proper way of ‘invoking’ the functionality. (E.g. Turn the key in the ignition to start the car).
-The advent of automatic transmissions from manual transmissions is analogous to ‘raising the level of abstraction’.
-It is possible that some people may want or need to know more low-level details, but our methods should be designed so that people who wish to remain blissfully ignorant, can do so.