Java Methods

 

A Java method is a set of Java instructions put together to execute a task. A Java method can belong to only one class. However, different classes can have methods with the same name or signature.

Every Java method has a method header and a method body.

At the bare minimum, a Java method is declared as

<access modifier> <return type> <method name>(<arguments>) 1

{

<method body> 2

}

The components in part 1 constitute the method header while the method body is the part that starts with { and ends with }. The method body is a code always a block. For example, let;s take a look at the following method that calculates the area of a rectangle and returns it.

public int getArea(int width, int height) {

1 2 3 4

return width * height;

5

}

The parts 1, 2, 3 and 4 are called the method header. 5 is the method body.

Now, let’s take a closer look at the components of getArea method.

1- public is the access modifier: Can be public, protected, private or none, in which case it is default access.

2- int is the return type: Can be an object, a primitive or if the method does not return something to its caller, it is void.

3- getArea is the method name: Name of the method used when the method is accessed. Method names follow Java method naming conventions. For example, a method name cannot start with a number.

4- int width, int height are the arguments: getArea method has two arguments, width and height. Both arguments are of int type. Arguments of a method are inside ( ) following the method name. If a method has more than one argument, they are separated by commas.

5- method body: The method body is the part of the method that is between the curly braces at the beginning and end of the method. It contains the logic that is executed when the method is invoked.

In addition to the bare minimum, the following can be the part of a method header:

  • non-access modifier static if the method is static
  • non-access modifier final keyword if the method is final.
  • throws keyword and the exceptions thrown by the method, separated with commas, if the method throws exceptions

What’s a method signature?

The name of a method and its arguments constitute a method’s signature. The other parts of the method definition, like access modifier or the return type, are not part of the signature of a method. Still, in practice, everything other than the method body are referred to as the method signature. It is important to keep in mind that, anywhere method signature is used as a reference, only the method name and the arguments are taken into account. For example, while determining if a class has the same method defined more than once, the signatures of the methods of the class are compared. A class cannot have two or more methods with the same name and arguments even if the methods have different return types. However, if the method names and arguments are the same but the order of the arguments are different, this is valid because this changes a method’s signature.

Let’s take a look at the signature of main method which is the entry point for the execution of every Java method. The signature of the main method is

main(String [])

However, in practice, we refer to the signature of the main method as

public static void main(String [] args)

As another example, we can take a look at the signature of the getArea() method we defined in the previous section. The signature of the getArea() method is

getArea(int, int)

but in practice, we may refer to the signature of the getArea method as

public int getArea(int width, int height)

The method signature is part of the method declaration and it is used by the Java compiler to determine uniqueness in a number of concepts like method overloading.

return keyword

return keyword is used inside the body of a method to return the program flow to the method’s caller. If a method declares a return type other than void, it is required to return a value of the declared return type. In a void method, the return keyword is used alone as a statement to return from the method to the method’s caller without returning a value. In other words, when the program flow encounters a return statement inside a void method, it exits the method and the program flow goes back to the method which called the void method.

method → call void method → return → back to the caller method (add a picture)

For void methods, using return inside the body is optional and not using it does not cause a compiler error. Methods that declare a non-void return type cannot use use return keyword alone as a statement as they are required to return a value to the caller.

Depending on the return type, methods are classified into two types.

1- Non-void methods

Non-void methods return a value. If a method’s return type is not void, it is required to return the program flow to its caller with a return statement. The return type in the method declaration and the type of the value that is returned by the method are required to be the same. Any other case causes a compiler error.

Let’s take a look at the following method as an example.

public String getFullName(String firstName, String middleName, String lastName) {

return firstName + “ “ + middleName + “ “ + lastName;

}

The return type of getFullName() method is declared as a String in the method definition. That means this method can return only a variable of String type. Inside the body of the method, the full name of a person is formed as a String by concatenating together firstName, middleName and lastName, each separated by a single space and then returned.

The only exception to requirement returning a variable for non-void methods is when the method throws an exception. If the method throws an exception before returning a value, the program flow ends before a value is returned. We will talk about exception in great detail in the Exceptions chapter.

2- Void methods

Void methods do not return a value to their callers. A void method’s return type is void.

public void printFullName(String fullName) {

System.out.println(“This person’s full name is “ + fullName);

}

printFullName() method is a void method. When it is called, it prints the fullName that is passed to it as an argument on the console.

The following version of the printFullName method does the same as the version defined above.

public void printFullName(String fullName) {

System.out.println(“This person’s full name is “ + fullName);

return;

}

Once all the statements inside a method are executed successfully, the program flow returns to the method’s caller. The return statement we added to the end of the method just makes it explicit and does not have an additional functionality. Therefore, it is almost always omitted.

Returning a value inside the body of a void method causes a compiler error.

Method access

Methods of a class are accessed using the . operator. A Java class can have define two types of methods: instance methods and static methods. Instance methods belong to an instance of the class. Static methods belong to all instances of the class and cannot be invoked separately with every instance. The access is required to happen through an instance of the class for instance methods. For static method calls, the access is typically through the class name but access through an instance is also valid. The method access formats for static and instance methods are as follows.

Static method calls:

<class name>.<static method name>(<method arguments);

Instance method calls:

<object name>.<instance method name>(<method arguments>);

Let’s see how static and instance methods of a class are defined and invoked with examples.

Instance methods:

Instance methods belong to an instance of a class and they can only be invoked by an object initialized from the class that owns the method.

Let’s define a Circle class that has a method, getArea(), that calculates the area of the circle.

public class Circle {

private int radius;

public Circle(double radius) {

this.radius = radius;

}

public double getArea() {

return 3.14 * radius * radius;

}

public static void main(String [] args) {

Circle circle = new Circle(2);

System.out.println(“The area of a circle with radius “ + radius + “ is “ + circle.getArea());

}

}

Circle class has a one-arg constructor method that accepts the radius of the circle as a double. getArea() method of the Circle class is an instance (non-static) method; it does not have static keyword in its declaration. Therefore it is invoked through an instance of the Circle class. This method calculates the circle’s area by getting the square of the radius that is passed in the constructor method and multiplying it by the double representation of the Pi number. Inside the main method, a new Circle object with the name circle is initialized from Circle class with radius 2. Following this, the instance method getArea() is called through the circle instance variable to calculate the area of the circle and the following String is printed on the console.

The area of a circle with radius 2 is 12.56

Static methods

Static methods belong to a class instead of an instance of a class. Such methods are shared by all instances of the class instead of a specific instance. Unlike instance methods, these methods can be invoked without initializing the class, using the class’ name. static keyword is used to declare a method as static.

public class CubeHelper {

public static void printVolume(int sideLength) {

System.out.println(“The volume of the cube with side length “ + sideLength + “ is “ + sideLength * sideLength * sideLength);

}

}

public class Example {

public static void main(String [] args) {

CubeHelper.printVolume(3);

}

}

Here in this example, printVolume() method belongs to all instances of the CubeHelper class. In other words, it’s a class method, not an instance method and therefore the class itself is the proper means to call this method through.Inside the main method, printVolume method of CubeHelper is called using the class name, without initializing in instance. The output is

The volume of the cube with side length 3 is 27.

Because a static method belongs to the class, static methods have access to only the static variables and methods of the class that they belong to. Calling an instance method or variable can be done only through a class instance. A static method needs to initialize a class first to access its instance variables and methods.

Let’s see how the access to static methods and variables work with an example.

public class Rectangle{

public int width;

public int height;

public static int DEFAULT_WIDTH = 4;

public static int DEFAULT_HEIGHT = 8;

public static int getDefaultArea() {

return DEFAULT_WIDTH * DEFAULT_HEIGHT;

}

public int getArea(int sideLength1, int sideLength2) {

return sideLength1 * sideLength2);

}

public static void main(String [] args) {

/***************************

This would cause a compile error.

sideLength1 = 3;

sideLength2 = 5;

System.out.println(“If sideLength1 is “ + sideLength1 + “ and sideLength2 is “ + sideLength2 + “, the area of the rectangle is “ + sideLength1 * sideLength2);

************/

//This is legal.

System.out.println(“Using the default parameters.”);

System.out.println(“width: “ + DEFAULT_WIDTH + “, length: “ + DEFAULT_LENGTH + “, area of the rectangle: “ + getDefaultArea());

}

}

The rectangle class has two instance variables: width and height. It declares one instance method: getArea(). Trying to set values to the instance variables and calling getArea directly inside main method causes a compile error because the variables and method accessed by the static main method are not static. DEFAULT_WIDTH, DEFAULT_HEIGHT and getDefaultArea() methods of Rectangle class are declared static. On the other hand, the static method getDefaultArea() can access the static DEFAULT_WIDTH and DEFAULT_HEIGHT variables of Rectangle class. Inside the main method, both the static variables and the static getArea() method are accessed by the static main method. Again, this is allowed because the caller and the variables and method being called are all static.

Static methods have many uses in Java. When used the right way, static methods help the programmers avoid unnecessary class initializations to call a method and keep the code more readable. On the other hand, using static methods unnecessarily is not the best strategy while doing object-oriented programming as it reduces the flexibility of the code since static methods cannot be overridden. Static methods are the most useful for keeping the logic that will be shared by all instances of a class. Utility classes or helper classes can be good examples for this.

Method calls and control flow

Control flow in Java corresponds to the order by which the JVM executes the instructions in a Java program. The flow of control always starts with the main method, then follows the statements in the methods called by main. Once the program flow is inside a method, it executes the instructions inside the method sequentially. The flow exits the method when:

1- All the statements inside the method are executed successfully.

2- A return statement is encountered.

3- An exception is thrown.

A method cannot have any statements in the code after a return statement or throwing an exception unless the execution of the code following these two depends on different conditions.

Optionally, void methods can have the return statement inside the method body somewhere other than the end of the method, to return the program flow to the caller. Mostly, this is done when a condition inside the method body is satisfied and executing the remaining instructions inside the method is no longer required. For example, let’s change the printFullName() method a little bit and add a condition.

public void printFullName(String fullName) {

if (fullName.length <= 1) {

System.out.println(“No full name can be one character long.”);

return;

}

System.out.println(“This person’s full name is “ + fullName);

}

The condition we added to the method on line 1 checks the number of characters that the fullName argument contains. If the number of characters contained is 1 or 0, we know that this is not a valid case. So, in this case, the statement on 6 is not executed. We just print an error message on the console and return from the method.

printFullName(“a”)

This generates the output

No full name can be one character long.

However, if the input fullName has more than 1 characters in it, the method does not return and print the fullName argument on the console.

printFullName(“James West”)

generates the output

This person’s full name is James West.

In this method, if fullName passed to the method is null, the program flow is returned to the caller of this method, using return.

Now let’s take a look at a non-void method.

public int getArea(int width, int height) {

System.out.println(“Calculating area…”);

return width * height;

//This would cause a compiler error.

//System.out.println(“Done.”);

}

Here in this method, first some text is printed on the console and then the area is calculated and returned. Putting any other statement after the return statement would cause a compiler error.

Method overloading

Java language does not allow defining two methods with the same signature in a class but it allows a class to have two or more methods with the same name but different signatures. This feature is called method overloading. If two or more methods have the same name in a Java class with different signatures, such methods are called overloaded methods. For example, as we have seen in previous examples, a Java class can have a no argument constructor while it also has a parameterized constructor. In this case, the constructor method of the class is referred to as overloaded.

Let’s define a class that sums up integers with overloaded methods.

public class MyClass {

public int sum(int i1, int i2) {

return i1 + i2;

}

public int sum(int i1, int i2, int i3) {

return i1 + i2 + i3;

}

public static void main(String [] args) {

System.out.println(“Sum of 1 and 2 is “ + sum(1, 2));

System.out.println(“Sum of 1, 3 and 5 is “ + sum(1, 3, 5));

}

}

The output is

The sum of 1 and 2 is 3.

The sum of 1, 3 and 5 is 9.

In this class, we define two methods named sum, but with different signatures. The first one takes two arguments while the second one takes three arguments. The method signatures are as follows:

1- public int sum(int, int)

2- public int sum(int, int, int)

Because the signatures are different, Java allows defining two methods with the same name inside this class and the sum method can be referred to as an overloaded method.

Java does not allow overloading a method if the argument names are different but signatures are the same. For example having the following sum methods

public int sum(int i1, int i2) {

return i1 + i2;

}

public int sum(int integer1, int integer2) {

return i1 + i2;

}

public void sum(int intg1, int intg2) {

System.out.println(“The sum of “ + intg1 + “ and “ + intg2 + “ is “ + (intg1 + intg2));

}

is not allowed because all three methods have the signature

sum(int, int).

Method signatures are the only thing taken into account by Java while determining if a method is overloaded properly or not. It is not important whether the method bodies are the same or not.

If two methods in a class has the same name and arguments, but with a different argument order, that is allowed. The following two methods are legally overloaded when they are declared in the same class.

//Method signature: printPersonInfo(String, int)

public String printPersonInfo(String name, int age) {

System.out.println(name + “ is “ + age + “ years old.”);

}

//Method signature: printPersonInfo(int, String)

public String printPersonInfo(int age, String name) {

System.out.println(name + “ is “ + age + “ years old.”);

}

%d bloggers like this: