METHODS IN JAVA

signature definition static overriding overloading Exercises

You can think of methods as the verbs in the Java language; methods do something. You have already used methods in some of your coding challenges. For example, in working with strings, you might have put something like this:

char nextLetter = testString.charAt(i);

or this:

int location = testString.indexOf("e");

Both of those code statements are examples of method calls. When you go to the API Specification and look at class String, you see the Method Summary-- a list of all the methods available in that class. It starts out like this:

Method Summary
char charAt(int index)

Returns the character at the specified index.

One of the available methods listed in the summary is named "charAt" and another is named "indexOf." The methods are called with the standard syntax of:

object.methodName();

The object must be an instance of the class that owns the method. Class String owns the "charAt" method, so the object must be a variable of the type String in order to call the method. Evidently, the variable named "testString" in the code samples above has already been declared to be of type String.

As we said above, methods do something. The "charAt" method will tell you which character appears at a particular location in the string. Of course, you have to tell it which location you have in mind. This information is conveyed by sending an argument (also known as a "parameter") in the parentheses. For this particular method, the argument must be an integer. How did I know that I needed to send an integer in the parentheses? The API Specification tells you that when you look up the method. From the method summary, you can click on the name of the method and you will see this detail:


charAt

public char charAt(int index)
Returns the character at the specified index. An index ranges from 0 to length() - 1. The first character of the sequence is at index 0, the next at index 1, and so on, as for array indexing.

You see that the parentheses contain a variable of type int, so you know that's the proper argument when you call the method. You don't actually type the word "int" when you go to call the method in your code. You just make sure that whatever variable you put in the parentheses is in fact a variable of type int. The variable can be named anything you want; it doesn't need to be called "index." For example, you might be calling the charAt method inside of a for loop, using a loop counter variable named "i":

for (int i=0; i<5; i++){

char nextLetter = testString.charAt(i);

}

The argument might be an actual number, too, as seen here:

char firstLetter = testString.charAt(0);

Not all methods require an argument, but you still need to use the parentheses. For example, here is another method from class String in the API Specification:


trim

public String trim()
Returns a copy of the string, with leading and trailing whitespace omitted.

As the API Specification explains, the trim method cuts white space off the end of strings. The parentheses are empty, indicating that there will be no argument. To call the method, you would do something like this:

String trimmedString = testString.trim();

So be sure to remind yourself about using parentheses in method calls. Every single method call you do will require parentheses. If you forget them, the compiler gets confused and thinks that you are referring to a field rather than a method. In fact, you should experiment with leaving them off deliberately and then see what kind of error message you get.


Method Signature

Let's look again at this example of a method call:

int location = testString.indexOf("e");

It should be clear why there is the string "e" inside the parentheses. This method requires something of type String to be sent in as an argument. The "indexOf" method will then go and look to see where there is an "e" inside of testString. Once it finds the first occurrence of "e," it will send that information back to me in the form of an integer. I decided to record that information in a variable called "location." How did I know that the answer would come back as an integer? Again, the API Specification told me:

public int indexOf(String str)

The word "int" right after the word "public" is telling me the return type of the method. It will be sending me something of type int, and I need to be ready to catch the thing it sends me. That's why I set up an int variable and used the assignment operator (=). That type of code statement is known as using the results of a method call in order to assign the value of a variable.

The results from the method call could be any type of variable that Java allows, including variable types that you make up yourself or ones that you find somewhere in the API Specification. Class Component has a method named getBackground() that will return to me the color of that component. Thus, the return type for that method would be Color:

public Color getBackground()

If I want to call that method in my code, I need to be ready to catch the Color value that it will send me. I can do that by storing it in a variable of my own:

Color currentColor = myButton.getBackground();

and now the variable currentColor is available for use later in the program. I might want to use it to set the color of a label:

myLabel.setBackground(currentColor);

The setBackground method requires an argument of type Color, and that's what I sent it. I knew that it needed that kind of argument because I looked it up in the API Specification.

When you go to look up a method in the API Specification, you are seeing what's known as the method's "signature." Signature refers to all of these aspects:

accessLevelreturnTypemethodName(argument(s))
publicbooleanendsWith(String suffix)

I found the endsWith method listed in class String in the API Specification. Just by reading its signature, I can tell several helpful things. First off, it's a public method, so I will have access to it to use in my own program. Next, the return type is boolean, so I know it will be sending me back an answer of true or false that I can use in my program when I call this method. The bold type tells me the method's name. Last, I see that it takes something of type String as its argument, so that's what I will have to send in when I call it. You can think of the argument as input to the method, and the return as output from the method. The "ends with" method consumes a String and produces a boolean.

If I want to call that method, I just have to be sure I follow what the signature is telling me to do. This method call will work:

if (myString.endsWith("ism") == true){

Then I just have to decide what I want the program to do if this particular string ends in "ism." You can see here that I didn't bother storing the answer to the "endsWith" question in a separate variable. I just wrote a conditional statement to immediately check if the answer was true or not. Sometimes you use the result of a method call to assign a variable, sometimes you use the result in a conditional statement, and sometimes you use the result as the argument for some other method call.

By the way, not all methods return a result. In that case, the return type is simply called "void."

keyhole logo
void
public void paint(Graphics g){

The keyword void acts as a place holder, because the compiler will always look for a return type in the method signature.


Method Definition

Sometimes, you go to the API Specification and you don't find the method you're looking for. You think to yourself, "I wish there were a way to do this...." Well, you can just go ahead and create that method yourself. Then you can call on that method whenever you need it. You did this in Basic Programming when you wrote your own subprograms using the keyword SUB. Either way, you are creating a subroutine.

To create your own method, you start with the method declaration that gives the signature of the method. This is the general syntax:

method signature{

method body

}

You type the signature the same way that you see it written for methods that already exist. You will include these elements:

accessLevel returnType methodName(argument(s))

The access keyword is optional, actually. Only the return type and method name are mandatory. For access, you can specify "public," "private" or "protected." We will learn more about those later. For now, just use "public" or leave it blank.

The braces enclose the body of the method, where you include everything that the method does. You will have things like variable assignments, loops, "if" blocks, and calls to other methods. All of those procedures are known as the implementation of the method--how it accomplishes its task. Don't try to define another method inside of your method body, however. Each method definition gets its own set of braces.

Here is a very simple method that takes two numbers and returns their average:

keyhole logo
return
public float average(float first, float second){

float averageValue = (first + second)/2;

return averageValue;

}

As you can see, the implementation of this method teaches the computer how to average two numbers. The keyword "return" is very important, since it sends the correct value back to the calling program. Unless your method's return type is void, you must have a return statement.

Here is an example of a method with a more complicated implementation. I created it when I was writing a program for a card game.

void switchPlaces(Card firstCard, Card secondCard){

int temp = firstCard.getDeckPosition();

firstCard.setDeckPosition(secondCard.getDeckPosition());

secondCard.setDeckPosition(temp);

displayCard(firstCard);

displayCard(secondCard);

System.out.println("moving the " + secondCard.toString());

}

This method takes two cards, switches their positions in the deck, and draws them on the screen in their new positions. In the method declaration, I indicated that it needs two arguments, each of type Card. The keyword "void" indicates that nothing will be returned from the method.

In the body of the method, I created a variable, temp, which has a scope that lasts only for the life of the method. Then I called two methods, "getDeckPosition" and "setDeckPosition", that belong to class Card. You can tell those methods belong to class Card because they are being called by variables, firstCard and secondCard, that are of type Card. After that, I called a method, "displayCard," that belongs to the class I was writing at the time. You can tell that it doesn't belong to some outside class, because it is called simply by its name, without reference to an object that is calling it. Evidently, the signature of "displayCard" requires that it be sent an object of type Card. Finally, I included a System.out.println statement as a way to send a message to myself so I could see which card was being moved at that time. Those little messages really help when you're trying to find errors in your program. To see more of this program, look at the code for Solitaire Simulator. You'll see that the code is just one method definition after another, with each definition block separated by a blank line.

Sometimes the methods that you define are your own idea and sometimes they are required by an interface that you are implementing. You'll see an example of that when you go to put a mouse listener in your applet. To implement the MouseListener interface, there are five required methods which you can find in the API Specification. They look like this:

public void mouseClicked(MouseEvent e)

It's always important to pay attention to signature. If you did this instead:

public void mouseClicked()

The compiler wouldn't even recognize it, because it is not the correct signature. It would yell at you for not including the required mouseClicked method. Try making that mistake and see what kind of error message you get.


Static Methods

You may have looked up some methods in the API Specification and noticed the keyword "static" stuck into the signature of the method. For example, this method from class String is very handy:

keyhole logo
static
public static String valueOf(int i)

I can see from the signature that the method takes a variable of type int and returns it as a String. When I go to call the method, I do it like this:

String numberString = String.valueOf(11993451);

This looks very similar to our previous example of calling a method from class String:

char nextLetter = testString.charAt(i);

with one important difference: The "charAt" method was called by the object testString-- a variable of type String. The "value of" method was not called by a variable at all. It was called by the class itself, namely class String. When the API Specification tells you that a method is static, you don't need to create an instance of the class to call the method; you just use the name of the class. Static is probably not a very good name for this situation. It might be better to refer to them as "class methods" or "general methods." They are used very frequently when working with the class Math that you can find in the API Specification. All of the methods in class Math are static, so when you go to call them, you do it like this:

int height = Math.sqrt(leg1*leg1 + leg2*leg2);

double randomDigit = Math.random()*10;

You don't try to make a variable of type Math when you want to find the square root of a number or use various other mathematical functions. You just call Math.methodName();.

Both methods and fields can be static. Math has a static field that will give you a very good approximation of the value of pi. You might use it like this:

double circumference = 2 * Math.PI * radius;

You will also find some handy static fields from class Color, where they have pre-mixed some frequently used colors for you. You can say:

helloLabel.setBackground(Color.black);

which saves you the trouble using the class constructor to create that color. Color is the name of the class. You didn't need to create a variable of type Color in order to be able to ask for that field. However, to get a custom color that you can store and use repeatedly, you would go ahead and make an instance of the class-- a variable of type color:

Color foreColor = new Color (0, 160, 160);


Method Overriding

You have been using method overriding with your applets. Class Applet already has a method called "init." This is because the browser will automatically look for that method, so it must exist. The "init" method that comes with class Applet, however, is empty and doesn't actually do anything. If you want "init" to do something, you have to write your own version, like this:

public void init(){

setColor(Color.black);

setSize(200,300);

}

You weren't calling the "init" method, you were defining it to do what you wanted to do to initialize your applet. Since your "init" method has exactly the same signature as class Applet's init method, the browser recognizes your "init" method and goes ahead and runs it. In fact, it runs your "init" instead of class Applet's "init," because yours takes precedence. This is what is known as method overriding. Your method overrides class Applet's method.

You will also probably want to override class Applet's "paint" method, which it inherited from class Container. If you look in class Container in the API Specification and check on its paint method, you will see that it overrides the paint method it inherited from class Component. Unlike "init, " the paint method is not empty and it may end up erasing some of your graphics unless you create your own paint method so that it draws exactly what you want. If you are having a problem with the graphics of your applet, it is probably due to the highly-annoying paint method. When you go to override paint, you have to use the same signature that is used in class Container:

public void paint(Graphics g){

g.setColor(Color.red);

g.drawOval(12,20,50,50);

}

Class Applet's method takes an argument of type Graphics, so your paint method must do that also. If you forget to include that, the compiler won't warn you about it. But your method will just sit there and never get called. By the way, class Applet's paint method gets called fairly frequently. Every time something happens on the screen to cover up the applet, or resize it, or change its appearance in any way, it needs to be repainted. The paint method is then called, without anybody asking you if you'd like it to be called. That's why you need control over the paint method, so that you can say what it means to repaint your applet. The graphics argument is important because when the browser calls paint, it is handing you the graphics environment that will be used to do the painting.

One nice feature about method overriding is that you still have the option to call the method that you overrode. You can choose whether you want your own paint method or the paint method that came from class Applet. Here's how that might work:

keyhole logo
super
public void paint(Graphics g){

super.paint(g);

g.setColor(Color.red);

g.drawOval(12,20,50,50);

}

The keyword super is used to signify the superclass of your applet, namely class Applet. When you use it, you're saying "call the paint method of my superclass." That paint method is very good at erasing things, so you might want to call it first and then continue with your own graphics statements. When you override a method, you haven't lost access to the original version of the method. You can call either or both.

Here is another example of overriding a method. If you look in class Object in the API Specification, you will see that it has a method called "toString." The purpose of this method is to return a phrase that describes the object in question. Since every variable (except for a primitive) is an object, the "toString" method automatically exists for all classes. When I made class Card, it inherited the pre-existing "toString" method from class Object. I decided, though, that I wanted it to return a string especially meaningful for a playing card, so I wrote my own "toString" method inside of class Card:

public String toString(){

return indexName+" of " + suitName;

}

Now when I ask for someCard.toString(), it will send back something like "King of Hearts" to my program, whatever card that variable of type Card happens to be. I chose to override the existing "toString" method.

You can override any method you like in Java, unless it happens to be defined with the keyword "final." Most methods are not final. To find out, you would check the API Specification. It would look like this:

keyhole logo
final
public final int read(byte[] b)

Method Overloading

Method overloading is one of the more amazing features about Java. It means that you can write many different versions of the same method, and call them by the same name. The way you tell them apart is by looking at the arguments inside the parentheses. For example in class String, we saw this method:

public static String valueOf(int i)

which takes an integer as its argument. If you go to the API Specification, though, you will see many other methods also named "valueOf"--each accepting a different type of argument. There's a valueOf() method for other types of numbers, such as doubles and floats. The only restriction on method overloading is that all of the methods by the same name must have the same return type. So, all of the "valueOf" methods return an object of type String.

Also in class String, you will see four different versions of the method indexOf(). One has this signature:

public int indexOf(String str)

while another has this signature:

public int indexOf(String str, int fromIndex)

How does this help you? Well, the first version will start the search string at the beginning of the string that is calling the method, while the second version will start at whatever position you specify. Frequently you want to start at the beginning of the string, and if there were only one version of the method, you would have to specify position 0 all the time. It's nice to have a shorter version of the method where you don't have to bother stating the 0. And it's also nice to have a longer version available, in case you want to start at a position greater than 0. The two other versions of indexOf() allow you to send in a character as an argument to search for, instead of a string. This gives you even more flexibility.

Overloading is used frequently in situations where default values may often be used, and the programmer appreciates a short form of the method. This convenience is provided, while still offering the option of using non-default values when desired. You will see overloading frequently in the Constructor Summary of a class. We saw this when we went to put a label in our first applet. There are three different ways to make a label:

public Label()

public Label(String text)

public Label(String text, int alignment)

The constructor that asks for only a string will use the default value for alignment, which is left-justified. If that's what you want your label to do, you might as well use the simpler constructor. If you want the label to be center or right-justified, then you should use the constructor that allows you to specify your alignment. When you start to create your own classes, you will be able to make as many different constructors as you want, customized for a variety of situations.


Read more about methods: Sun Java tutorial.
David Eck's textbook.
He refers to methods as "subroutines" throughout the chapter.
Bruce Eckel's textbook


Exercises

  1. In your own code, find an example of using the result of a method call to assign the value of a variable.


  2. Write a method for averaging numbers that takes not just two floats but instead an array of floats as its argument. The method should return the average of all of the numbers in the array (even though you don't know how many will be in the array!).


  3. What happens when you forget the parentheses on a method call?


  4. In the "switchPlaces" method shown above, find the place where the result of one method call is used as the argument for another method call.


  5. Here is the signature of a method:

    public String spellNumber(int i)

    Now show how to call that method in code.


  6. Here is an example of a method call:

    Person singer = thatSong.getArtist()

    From what you see here, make a guess about the signature of that method.


  7. Here is the signature of a method required by the interface MouseListener:

    public void mousePressed(MouseEvent e)

    If you wrote it in your code like this:

    public void mousePressed(MouseEvent theEvent)

    would you get an error message or would it be okay? Explain.


  8. An example of method overriding above shows a toString() method designed for class Card. The method does not use the keyword static. The compiler would allow you to designate that as a static method, but it wouldn't make any sense to do so. Why not?

Previous Topic Java Home Page Syntax Sheet Next Topic