Previous lesson Back to the front Next lesson

Being Methodical


As an interlude from objects, we're going to look at methods. They are one of the single most important ideas in programming, allowing us to build large complex programs relatively easily - but I hope you'll see for yourself how useful they are. Fortunately we are going to build small, simple programs, just to get you used to using methods and (most important) writing your own.

So what is a method? It's pretty simple - it's a named chunk of Java which does some particular task. It's a lot like the idea of a function in maths: you put something in and you get something back. In Java, both putting anything in and getting anything back are optional. Don't worry, you'll see. Here's a program you should recognise:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
	}
}

Now let's add a method to it:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
	}

	void message() {
		System.out.println("Here's a message about methods");
	}
}

Before we try and run the program, let's break down exactly what the part in red means. The first thing to note is that every method has to have a name. This method is called message. You'll see that it's followed by a block - that is, some lines of Java code inbetween a pair of { } braces. Notice that it looks a lot like the Hello, World! part above. Why? Because that's a method too!

The name of the method always comes immediately before the round brackets ( ). Which means that the Hello, World! part is called main, because main comes just before the (. Method names are just like variable names - they can only contain letters, numbers and the underscore (_), and upper/lowercase is significant. They should also start with a lowercase letter and follow camel notation (you should remember what that means by now).

We said at the start that a method is like a function: you (usually) put something in, and you (usually) get something back. Just before the name of the method, we write what type we get back. In this case we have written void, which means we get nothing back. You can't have a variable of type void, it is only used to say that a method returns nothing (returns is the technical way to say what we get back).

After the method name, we always have a pair of ( ) brackets. We use these to say what we "put in" to the method. In this case we have written () immediately after message. The brackets are empty - this means that we put nothing into the method. To summarise, void message() means that we have a method called message, which returns nothing and which we put nothing into.

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
[nurmes]btg: 

Why doesn't the method print anything out? Because what we've done is just define a method. We haven't actually used it yet. Let's use it:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		message();
	}

	static void message() {
		System.out.println("Here's a message about methods");
	}
}

We have to make message a static method, because it is used in the main method, which is also static. Don't let it concern you, I'll explain this fully later, when we talk about objects some more.

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
Here's a message about methods
[nurmes]btg: 

Wherever we write message(); the Java code which belongs to the method is executed. Watch this:


class Hello {
	public static void main(String[] args) {
		message();
		message();
		System.out.println("Hello, world!");
		message();
	}

	static void message() {
		System.out.println("Here's a message about methods");
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Here's a message about methods
Here's a message about methods
Hello, world!
Here's a message about methods
[nurmes]btg: 

I hope you've got the hang of it by now. Writing message(); like this is called calling the method. But what's the point of doing things this way? Suppose we want to add something to the message:


class Hello {
	public static void main(String[] args) {
		message();
		message();
		System.out.println("Hello, world!");
		message();
	}

	static void message() {
		System.out.println("Here's a message about methods");
		System.out.println("Use methods to repeat things and save typing!");
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Here's a message about methods
Use methods to repeat things and save typing!
Here's a message about methods
Use methods to repeat things and save typing!
Hello, world!
Here's a message about methods
Use methods to repeat things and save typing!
[nurmes]btg: 

This program really explains itself - methods are useful for doing something lots and lots of times. This has loads of advantages in programming. You might remember having lots of very similar bits of Java in your Practical 2 (calculator) program. I used a simple method in mine - it was much smaller and easier to read, easier to make changes and fix mistakes, and it took much much less time to write. Methods are a good thing!

Remove some lines ready for the next part:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
	}
}

Now I'm going to write another method, but this time it will have a return value. This means we will "get something back" from the method. Remember before that we wrote void, to show that the method didn't have a return value.


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
	}

	static int number() {
	}
}

There it is. If you ignore the keyword static, we can see that the method is called number. Since the () brackets are empty, we don't put anything into it. Finally, we can see we get back an int (we say "number returns an int"; or "the return type of number is int").

But what does it all mean? Well, the first thing it means is that our program won't compile:

[nurmes]btg: javac Hello.java
Hello.java:5: Return required at end of int number().
    static int number() {
               ^
1 error
[nurmes]btg: 

Don't panic... think calmly. The error message tells us Return required at end of int number(). It might as well say Return required at end of method - when it says int number() it is using the full name of the method, that's all. So we need a return. What's that? Allow me to demonstrate:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
	}

	static int number() {
		System.out.println("In the number method");
		return 3;
	}
}

And now the program will compile:

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
[nurmes]btg: 

It's not surprising that nothing much happened. As before, we need to call the method, otherwise the Java code which it contains never gets executed.


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		number();
	}

	static int number() {
		System.out.println("In the number method");
		return 3;
	}
}

Where's the three?

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
In the number method
[nurmes]btg: 

The message shows us that the method has been called, but where is the three? The answer is simple: we haven't stored it anywhere. When we have a method which doesn't return a value (such as the previous example called message) we just call it like this. When we have a method which does return a value, we can do what we've done above. However the value is just thrown away - it's pretty pointless most of the time. It's more useful to store the value in a variable, like this:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		int returnValue = number();
		System.out.println(returnValue);
	}

	static int number() {
		System.out.println("In the number method");
		return 3;
	}
}

Now we've created a variable for the return value of number, and stored it there, then printed it out.

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
In the number method
3
[nurmes]btg: 

Can you see what happens? First, the program evaluates ("works out") the part which says number();. Then it takes the return value of the method and stores it in the variable returnValue, which is printed out. We can have methods which return any type at all - one of the primitive types, or an object such as a string. Allow me to demonstrate an example:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		String returnValue = number();
		System.out.println(returnValue);
	}

	static String number() {
		System.out.println("In the number method");
		return "Five and a half";
	}
}

Notice which parts have changed. I needed to say that the method returns a string so that I could write return "Five and a half"; without any problems. I also needed to make the variable returnValue of type String, so I could say returnValue = number() without any problems. It even works:

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
In the number method
Five and a half
[nurmes]btg: 

Now let's move on to a method which you can put something into.


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
	}

	static void printNumber(int n) {
		System.out.println(n);
	}
}

So here we've made a new method. By now you should be confident to say that it is called printNumber and has no return value. But notice that inside the round brackets we have written int n. This means that we have to put in an int when we call this method. We say that this int is a parameter of the method. Allow me to demonstrate.


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4);
	}

	static void printNumber(int n) {
		System.out.println(n);
	}
}

So we have called the method printNumber with 4 as a parameter. We can also say that we have passed the value 4 to printNumber. Enough jargon, what does it do?

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
4
[nurmes]btg: 

Exactly what it says in fact, printNumber(4) prints the number 4. Look at the printNumber method. Although we haven't created a variable n, we can write System.out.println(n);. When the method is called, a variable of type int called n is created, which contains the value 4. If we call the method again, we can put another value in n:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4);
		printNumber(6);
	}

	static void printNumber(int n) {
		System.out.println(n);
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
4
6
[nurmes]btg: 

Not too hard, is it? We can have a method with more than one parameter too:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4, 5);
	}

	static void printNumber(int n, int p) {
		System.out.println(n + " " + p);
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
4 5
[nurmes]btg: 

We can add as many parameters as we want like this. Notice that the order of parameters is significant - the first number passed to the method is put in n and the second is put in p. We can also have parameters of different types:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4, "four");
	}

	static void printNumber(int n, String p) {
		System.out.println(n + " " + p);
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
4 four
[nurmes]btg: 

We can pass values from variables too, like this:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		int num = 4;
		String name = "four";
		printNumber(num, name);
	}

	static void printNumber(int n, String p) {
		System.out.println(n + " " + p);
	}
}

I won't run this, the output is the same. Now let's combine these two ideas, and create a method with some parameters and a return value. It's really not hard at all:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		System.out.println(bigger(3,4));
	}

	static int bigger(int a, int b) {
	}
}

Notice that I've printed out the return value of the method directly (System.out.println(bigger(3,4));). I hope this doesn't scare you too much. We don't have to even put it into a variable first - what we get back from the method is an int value, not a variable, so we can just print out the value.

Now remember I said earlier that a method does a particular task? This method simply has to return the larger of the two parameters a and b. This is a good chance to show you that we can have more than one return statement.


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		System.out.println(bigger(3,4));
	}

	static int bigger(int a, int b) {
		if (a >= b)
			return a;
		else
			return b;
	}
}

Let's try it out:

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
4
[nurmes]btg: 

Well it works. I like to put a line at the very top of each method that prints out the method name and all the parameters. That way it's easier to keep track of what's going on, especially in big complex programs. Let me show you:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		System.out.println(bigger(3,4));
	}

	static int bigger(int a, int b) {
		System.out.println("bigger(" + a + ", " + b + ")");

		if (a >= b)
			return a;
		else
			return b;
	}
}

That extra line looks quite complicated, but if you look closely all I've done is glued the values of a and b together, with some little bits of text to make it look all nice:

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
bigger(3, 4)
4
[nurmes]btg: 

Now ain't that purdy? We can see which method we've called, and what parameters it was given. Another thing you can do is create more than one method with the same name. They can have different numbers of parameters, or different types of parameters (or even the same types in a different order I suppose!). You should only use this when you want the methods to all perform the same task, but with different parameters.


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4);
	}

	static void printNumber(int n) {
		System.out.println(n);
	}
}

Remember me? Now let's add a few variations:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4);
	}

	static void printNumber() {
		System.out.println("N/A");
	}

	static void printNumber(double d) {
		System.out.println("double value " + d);
	}

	static void printNumber(int n) {
		System.out.println("int value " + n);
	}
}

Now we have three versions of printNumber, with different parameters. Remember that double is used for numbers with a decimal portion. The compiler is smart enough to figure out which is which when we call them:


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber();
		printNumber(2.1);
		printNumber(4);
	}

	static void printNumber() {
		System.out.println("N/A");
	}

	static void printNumber(double d) {
		System.out.println("double value " + d);
	}

	static void printNumber(int n) {
		System.out.println("int value " + n);
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
N/A
double value 2.1
int value 4
[nurmes]btg: 

It's pretty clever really. The only bit which isn't obvious is with little whole numbers, like 4. It could be a byte, a short, an int or a long. Let's see, shall we?


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4);
	}

	static void printNumber(int n) {
		System.out.println("int value " + n);
	}
}

Yeah, and the rest...


class Hello {
	public static void main(String[] args) {
		System.out.println("Hello, world!");
		printNumber(4);
	}

	static void printNumber(byte b) {
		System.out.println("byte value " + b);
	}

	static void printNumber(short s) {
		System.out.println("short value " + s);
	}

	static void printNumber(int n) {
		System.out.println("int value " + n);
	}

	static void printNumber(long l) {
		System.out.println("long value " + l);
	}
}

 

[nurmes]btg: javac Hello.java
[nurmes]btg: java Hello
Hello, world!
int value 4
[nurmes]btg: 

Even tiny little 4 is an int - in fact all values which will fit in an int are. Some of the really big ones will be a long instead, but you don't often write them out this way.

We've waffled on plenty about methods. Now you know how to add them to your own programs, things should get a lot easier. It also means we can go on to some really fun stuff, creating our own objects! So do us a favour, and rate this lesson:

But
what
do
you
think?
This lesson was...
What don't you understand? Other comments?
Excellent
OK
Poor
Your email (optional)
Go on to Take Car

Too patronising? Too complex? Typing error? Offended by traffic cones? Got a question or something I should add? Send an email to ben_golding@yahoo.co.uk !

visits to this site

The contents of this site are copyright of Ben Golding