Methods
Tags: java, programming, learning, beginners
Published: 2024-05-10 11:02:30

Methods can be used to define reusable code and organize and simplify coding. Suppose that you need to find the sum of integers from **1** to **10**, from **20** to **37**, and from **35** to **49**, respectively. You may write the code as follows:

```
int sum = 0;
for (int i = 1; i <= 10; i++)
 sum += i;
System.out.println("Sum from 1 to 10 is " + sum);
sum = 0;
for (int i = 20; i <= 37; i++)
 sum += i;
System.out.println("Sum from 20 to 37 is " + sum);
sum = 0;
for (int i = 35; i <= 49; i++)
 sum += i;
System.out.println("Sum from 35 to 49 is " + sum);
```

You may have observed that computing these sums from **1** to **10**, from **20** to **37**, and from **35** to **49** are very similar except that the starting and ending integers are different. Wouldn’t it be nice if we could write the common code once and reuse it? We can do so by defining a method and invoking it.

The preceding code can be simplified as follows:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n358fpssctu5j2rps4v.png)

Lines 5-11 define the method named **sum** with two parameters **i1** and **i2**. The statements in the **main** method invoke **sum(1, 10)** to compute the sum from **1** to **10**, **sum(20, 37)** to compute the sum from **20** to **37**, and **sum(35, 49)** to compute the sum from **35** to **49**.

A method is a collection of statements grouped together to perform an operation. In earlier chapters you have used predefined methods such as **System.out.println**, **System.exit**, **Math.pow**, and **Math.random**. These methods are defined in the Java library.

## Defining a Method

A method definition consists of its method name, parameters, return value type, and body.

The syntax for defining a method is as follows:

```
modifier returnValueType methodName(list of parameters) {
 // Method body;
}
```

Let’s look at a method defined to find the larger between two integers. This method, named **max**, has two **int** parameters, **num1** and **num2**, the larger of which is returned by the method. Below, illustrates the components of this method.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1ellgfpsovklpy37aml.png)

The _method header_ specifies the _modifiers_, _return value type_, _method name_, and _parameters_ of the method. The **static** modifier is used for all the methods here.

A method may return a value. The **returnValueType** is the data type of the value the method returns. Some methods perform desired operations without returning a value. In this case, the **returnValueType** is the keyword **void**. For example, the **returnValueType** is **void** in the **main** method, as well as in **System.exit**, and **System.out.println**. If a method returns a value, it is called a _value-returning method_; otherwise it is called a _void method_.

The variables defined in the method header are known as _formal parameters_ or _simply parameters_. A parameter is like a placeholder: when a method is invoked, you pass a value to the parameter. This value is referred to as an _actual parameter_ or _argument_. The _parameter list_ refers to the method’s type, order, and number of the parameters. The method name and the parameter list together constitute the _method signature_. Parameters are optional; that is, a method may contain no parameters. For example, the **Math.random()** method has no parameters.

The method body contains a collection of statements that implement the method. The method body of the **max** method uses an **if** statement to determine which number is larger and return the value of that number. In order for a value-returning method to return a result, a return statement using the keyword **return** is _required_. The method terminates when a return statement is executed.

Some programming languages refer to methods as _procedures_ and _functions_. In those languages, a value-returning method is called a _function_ and a void method is called a _procedure_.

In the method header, you need to declare each parameter separately. For instance, **max(int num1, int num2)** is correct, but **max(int num1, num2)** is wrong.

We say “define a method” and “declare a variable.” We are making a subtle distinction here. A definition defines what the defined item is, but a declaration usually involves allocating memory to store data for the declared item.

## Calling a Method

Calling a method executes the code in the method. In a method definition, you define what the method is to do. To execute the method, you have to _call_ or _invoke_ it. There are two ways to call a method, depending on whether the method returns a value or not.

If a method returns a value, a call to the method is usually treated as a value. For example,

```
int larger = max(3, 4);
```

calls **max(3, 4)** and assigns the result of the method to the variable **larger**. Another example of a call that is treated as a value is

```
System.out.println(max(3, 4));
```

which prints the return value of the method call **max(3, 4)**.

If a method returns **void**, a call to the method must be a statement. For example, the method **println** returns **void**. The following call is a statement:

```
System.out.println("Welcome to Java!");
```

A value-returning method can also be invoked as a statement in Java. In this case, the caller simply ignores the return value. This is not often done, but it is permissible if the caller is not interested in the return value.

When a program calls a method, program control is transferred to the called method. A called method returns control to the caller when its return statement is executed or when its method-ending closing brace is reached.
The complete program is used to test the **max** method:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fwjdf1iylfahqzivtms.png)

This program contains the **main** method and the **max** method. The **main** method is just like any other method except that it is invoked by the JVM to start the program.

The **main** method’s header is always the same. Like the one in this example, it includes the modifiers **public** and **static**, return value type **void**, method name **main**, and a parameter of the **String[]** type. **String[]** indicates that the parameter is an array of **String**.

The statements in **main** may invoke other methods that are defined in the class that contains the **main** method or in other classes. In this example, the **main** method invokes **max(i, j)**, which is defined in the same class with the **main** method.

When the **max** method is invoked (line 8), variable **i**’s value **5** is passed to **num1**, and variable **j**’s value **2** is passed to **num2** in the **max** method. The flow of control transfers to the **max** method, and the **max** method is executed. When the **return** statement in the **max** method is executed, the **max** method returns the control to its caller (in this case the caller is the **main** method). This process is illustrated in below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o32veqhzxd08ccyop32i.png)

When the **max** method is invoked, the flow of control transfers to it. Once the **max** method is finished, it returns control back to the caller.

A **return** statement is required for a value-returning method. The method shown below in (a) is logically correct, but it has a compile error because the Java compiler thinks that this method might not return a value.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qq8eedra4zm9hdiw4t2h.png)

To fix this problem, delete **if (n < 0)** in (a), so the compiler will see a **return** statement to be reached regardless of how the **if** statement is evaluated.

Methods enable code sharing and reuse. The **max** method can be invoked from any class, not just **TestMax**. If you create a new class, you can invoke the **max** method using **ClassName.methodName** (i.e., **TestMax.max**).

Each time a method is invoked, the system creates an _activation record_ (also called an _activation frame_) that stores parameters and variables for the method and places the activation record in an area of memory known as a _call stack_. A call stack is also known as an _execution stack_, _runtime stack_, or _machine stack_, and it is often shortened to just “the stack.” When a method calls another method, the caller’s activation record is kept intact, and a new activation record is created for the new method called. When a method finishes its work and returns to its caller, its activation record is removed from the call stack.

A call stack stores the activation records in a last-in, first-out fashion: The activation record for the method that is invoked last is removed first from the stack. For example, suppose method **m1** calls method **m2**, and **m2** calls method **m3**. The runtime system pushes **m1**’s activation record into the stack, then **m2**’s, and then **m3**’s. After **m3** is finished, its activation record is removed from the stack. After **m2** is finished, its activation record is removed from the stack. After **m1** is finished, its activation record is removed from the stack.

Understanding call stacks helps you to comprehend how methods are invoked. The variables defined in the **main** method are **i**, **j**, and **k**. The variables defined in the **max** method are **num1**, **num2**, and **result**. The variables **num1** and **num2** are defined in the method signature and are parameters of the **max** method. Their values are passed through method invocation. Below, illustrates the activation records for method calls in the stack.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uvcppnbscextioawm0dl.png)

When the **max** method is invoked, the flow of control transfers to the **max** method. Once the **max** method is finished, it returns control back to the caller.

## void Method Example

A **void** method does not return a value.

The preceding section gives an example of a value-returning method. This section shows how to define and invoke a **void** method. The program defines a method named **printGrade** and invokes it to print the grade for a given score.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vt3n703pf264k1jdwhus.png)

The **printGrade** method is a **void** method because it does not return any value. A call to a **void** method must be a statement. Therefore, it is invoked as a statement in line 4 in the **main** method. Like any Java statement, it is terminated with a semicolon.

To see the differences between a void and value-returning method, let’s redesign the **printGrade** method to return a value. The new method, which we call **getGrade**, returns the grade as shown below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b6zwpfpedgkr8diwy293.png)

The **getGrade** method defined in lines 10-21 returns a character grade based on the numeric score value. The caller invokes this method in lines 6-7.

The **getGrade** method can be invoked by a caller wherever a character may appear. The **printGrade** method does not return any value, so it must be invoked as a statement.

A **return** statement is not needed for a **void** method, but it can be used for terminating the method and returning to the method’s caller. The syntax is simply

`return;`

This is not often done, but sometimes it is useful for circumventing the normal flow of control in a **void** method. For example, the following code has a return statement to terminate the method when the score is invalid.

```
public static void printGrade(double score) {
if (score < 0 || score > 100) {
 System.out.println("Invalid score");
return;
 }
if (score >= 90.0) {
 System.out.println('A');
 }
else if (score >= 80.0) {
 System.out.println('B');
 }
else if (score >= 70.0) {
 System.out.println('C');
 }
else if (score >= 60.0) {
 System.out.println('D');
 }
else {
 System.out.println('F');
 }
}
```

## Passing Arguments by Values

The arguments are passed by value to parameters when invoking a method. The power of a method is its ability to work with parameters. You can use **println** to print any string and **max** to find the maximum of any two **int** values. When calling a method, you need to provide arguments, which must be given in the same order as their respective parameters in the method signature. This is known as _parameter order association_. For example, the following method prints a message **n** times:

```
public static void nPrintln(String message, int n) {
for (int i = 0; i < n; i++)
 System.out.println(message);
}
```

You can use **nPrintln("Hello", 3)** to print **Hello** three times. The **nPrintln("Hello", 3)** statement passes the actual string parameter **Hello** to the parameter **message**, passes **3** to **n**, and prints **Hello** three times. However, the statement **nPrintln(3, "Hello")** would be wrong. The data type of **3** does not match the data type for the first parameter, **message**, nor does the second argument, **Hello**, match the second parameter, **n**.

The arguments must match the parameters in _order_, _number_, and _compatible_ type, as defined in the method signature. Compatible type means that you can pass an argument to a parameter without explicit casting, such as passing an **int** value argument to a **double** value parameter.

When you invoke a method with an argument, the value of the argument is passed to the parameter. This is referred to as _pass-by-value_. If the argument is a variable rather than a literal value, the value of the variable is passed to the parameter. The variable is not affected, regardless of the changes made to the parameter inside the method. As shown below, the value of **x** (**1**) is passed to the parameter **n** to invoke the **increment** method (line 8). The parameter **n** is incremented by **1** in the method (line 13), but **x** is not changed no matter what the method does.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jngdvqvb2v6n1d3ykp9j.png)

Here's another program that demonstrates the effect of passing by value. The program creates a method for swapping two variables. The **swap** method is invoked by passing two arguments. Interestingly, the values of the arguments are not changed after the method is invoked.

```
package demo;

public class TestPassByValue {

	public static void main(String[] args) {
		// Declare and initialize variables
		int num1 = 1;
		int num2 = 2;
		
		System.out.println("Before invoing the swap method, num1 is " + num1 + " and num2 is " + num2);
		
		// Invoke the swap method to attempt to swap two variables
		swap(num1, num2);
		
		System.out.println("After invoking the swap method, num1 is " + num1 + " and num2 is " + num2);
	}
	
	/** Swap two variables */
	public static void swap(int n1, int n2) {
		System.out.println("\tInside the swap method");
		System.out.println("\t\tBefore swapping, n1 is " + n1 + " and n2 is " + n2);
		
		// Swap n1 with n2
		int temp = n1;
		n1 = n2;
		n2 = temp;
		
		System.out.println("\t\tAfter swappin, n1 is " + n1 + " and n2 is " + n2);
	}

}

```

Before the **swap** method is invoked (line 13), **num1** is **1** and **num2** is **2**. After the **swap** method is invoked, **num1** is still **1** and **num2** is still **2**. Their values have not been swapped. As shown below, the values of the arguments **num1** and **num2** are passed to **n1** and **n2**, but **n1** and **n2** have their own memory locations independent of **num1** and **num2**. Therefore, changes in **n1** and **n2** do not affect the contents of **num1** and **num2**.

Another twist is to change the parameter name **n1** in **swap** to **num1**. What effect does this have? No change occurs, because it makes no difference whether the parameter and the argument have the same name. The parameter is a variable in the method with its own memory space. The variable is allocated when the method is invoked, and it disappears when the method is returned to its caller.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qrhk6lt664ovgjvptsa.png)

For simplicity, Java programmers often say passing **x** to **y**, which actually means passing the value of argument **x** to parameter **y**.