Chapter 6:Understanding Java Functions: Syntax, Parameters, and Call by Value with Examples

Chapter 6: Mastering Java Functions/Methods

1. Introduction to Functions/Methods

Functions (also known as methods in Java) are blocks of code designed to perform a particular task. Imagine using a TV remote to adjust the volume or change channels. You don’t write the logic to increase or decrease the volume each time; instead, you press a button and the remote performs the task for you. This concept is similar to functions in programming. The logic for each button is predefined, and when pressed, the same logic is executed.

Similarly, in programming, functions are reusable blocks of code that can be invoked multiple times without rewriting the same logic. This not only saves time but also makes the code more organized and efficient.

Key Benefits:

  • Reusability: Write once, use multiple times.

  • Modularity: Breaks complex problems into smaller, manageable pieces.

  • Maintainability: Easy to update the function without touching the main logic.


2) Syntax of Function and Explanation

In Java, functions (also called methods) are a block of code that performs a specific task. The basic syntax of a function is:

returnType functionName(parameterList) {
    // Body of the function
    return value; // This is optional if the return type is void.
}
  • Return Type: Specifies the data type of the value the function will return. If the function does not return any value, it uses void.

  • Function Name: Identifies the function, typically in camelCase.

  • Parameter List: Variables passed to the function. These are optional and can be empty if no input is required.

  • Function Body: The code to be executed when the function is called.

  • Return Statement: If the function has a return type other than void, it must return a value of that type.

Analyzing the Main Function

In Java, the program execution always starts with the main function. Here's the basic structure:

public static void main(String[] args) {
    // Code to be executed
}
  • public: Accessible from anywhere.

  • static: Allows the method to be called without creating an instance of the class.

  • void: The main function doesn't return any value.

  • String[] args: Accepts command-line arguments (not mandatory to use in every program).

Example: Function to Print "Hello World"

public class PrintHW {
    // Function to print "Hello World"
    public static void PrintHW() {
        System.out.println("Hello World");
        return; // No return value because the function is void
    }

    public static void main(String[] args) {
        // Function call inside the main function
        PrintHW(); // This calls the PrintHW function
    }
}
  • void: The function PrintHW() doesn’t return any value. That's why we use void.

  • Function Call: In the main method, we call the PrintHW() function to execute it. The execution starts from the main method, and we explicitly call any other function from there.

Output:

Hello World

Functions vs Methods

In Java, functions are called methods when defined inside a class. So, function and method refer to the same thing in Java.


3) Syntax of Function with Parameters

A function can accept parameters (also called arguments) to operate on. The syntax for a function with parameters is:

returnType functionName(dataType parameter1, dataType parameter2, ...) {
    // Body of the function
    return value; // Optional if the return type is void.
}
  • Parameters (Formal Parameters): These are placeholders in the function that accept values when the function is called. For example, int a and int b in the example below.

Example: Function to Add Two Numbers

import java.util.Scanner;

public class Sum {
    // Function with two parameters: a and b
    public static int Sum(int a, int b) {
        int sum = a + b;
        return sum; // The sum is returned as the output
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); // Input scanner for user input
        System.out.print("Enter a: ");
        int a = sc.nextInt(); // First number (actual parameter)
        System.out.print("Enter b: ");
        int b = sc.nextInt(); // Second number (actual parameter)

        // Calling the function Sum with arguments a and b
        System.out.println("Sum of a and b is: " + Sum(a, b));
    }
}

Explanation:

  1. Function Declaration:

    • int Sum(int a, int b): The function Sum() accepts two parameters a and b. These parameters are used inside the function to perform the addition.

    • return sum: Since the return type of the function is int, the result of the addition (sum) is returned from the function.

  2. Formal Parameters: In public static int Sum(int a, int b), a and b are formal parameters because they are placeholders used within the function.

  3. Actual Parameters: In Sum(a, b);, the values provided by the user (a and b) are actual parameters (also called arguments). These are the values passed to the function during the function call.

  4. Multiple Functions: A class can have multiple functions, each serving different purposes. Here, the class Sum contains both the Sum() function and the main() function.

  • Parameters: int a, int b are called parameters (or formal parameters). They are placeholders that hold the values passed when the function is called.

  • Arguments (Actual Parameters): When we call Sum(a, b), we pass the actual values for a and b that are provided by the user.

Output:

Enter a: 5
Enter b: 7
Sum of a and b is: 12

Key Points:

  1. A class can have multiple functions, each performing different tasks.

  2. Parameters allow you to pass data to the function.

  3. Return type specifies what kind of value the function will return (or no return in the case of void).

By using functions with parameters, you can pass different inputs and get the desired result based on those inputs.


4. Parameters vs. Arguments

Parameters:

  • Defined in the function signature.

  • Act as placeholders for the actual values.

Arguments:

  • Actual values passed to the function during the function call.

5. Memory Allocation in Functions

When a function is called, the Java runtime allocates memory for its parameters and local variables on the call stack. Each time a method is invoked, it creates a stack frame. This stack frame contains:

  1. Parameters passed to the method.

  2. Local variables declared inside the method.

  3. Return address, which points to the next instruction after the method returns.

Once the method completes execution, its stack frame is removed from the call stack, freeing the memory.

Let’s visualize the memory allocation for the following example:

Code Example: Swapping Two Numbers

public class Swap {
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
        System.out.println("Inside swap: a = " + a + ", b = " + b);
    }

    public static void main(String[] args) {
        int a = 5;
        int b = 6;
        swap(a, b);
        System.out.println("After swap: a = " + a + ", b = " + b);
    }
}

Visualizing Stack Frames:

  1. Before calling swap():
    Only the main() method's stack frame is active. It holds the variables a and b.
|-------------------------|
|      [Main] Stack Frame  |
|-------------------------|
| a = 5, b = 6            |
|-------------------------|
  1. When swap() is called:
    A new stack frame for swap() is created on top of the main() stack frame. It holds the parameters a, b, and the local variable temp.
|-------------------------|
|      [swap] Stack Frame  |
|-------------------------|
| a = 5, b = 6            |
| temp = 5                |
|-------------------------|
|      [Main] Stack Frame  |
|-------------------------|
| a = 5, b = 6            |
|-------------------------|
  1. During execution of swap():

    • The values of a and b in the swap() stack frame are updated after the swap logic.

    • The temp variable stores the value of a (5), and a is updated to b (6). Then, b is updated to temp (5).

|-------------------------|
|      [swap] Stack Frame  |
|-------------------------|
| a = 6, b = 5            |
| temp = 5                |
|-------------------------|
|      [Main] Stack Frame  |
|-------------------------|
| a = 5, b = 6            |
|-------------------------|
  1. After swap() returns:
    The swap() method completes its execution, and its stack frame is removed from the call stack. The main() stack frame remains unchanged, meaning the values of a and b in main() are still 5 and 6, respectively.
|-------------------------|
|      [Main] Stack Frame  |
|-------------------------|
| a = 5, b = 6            |
|-------------------------|

Explanation:

  • Call by Value: In Java, when the swap() method is called, a copy of the values of a and b from main() is passed to the swap() function. Changes made inside the swap() function only affect the copies of a and b in the swap() stack frame.

  • The original values of a and b in main() remain unchanged because Java uses call by value.

  • The swap logic works inside swap(), but it does not affect the values in main() after the method returns.

Output:

Inside swap: a = 6, b = 5
After swap: a = 5, b = 6

The output shows that the variables were swapped inside the swap() method, but after returning to main(), the original values remain unchanged.


6. Call by Value vs Call by Reference

Java is a language that uses call by value. This means that when you pass arguments to a method, Java passes a copy of the value of the argument. As a result, changes made to the parameter inside the method do not affect the original value in the calling code.

Key Concepts:

  • Call by Value: The method receives a copy of the argument's value, not the actual reference to the variable.

  • Call by Reference: The method receives a reference to the original variable, so changes to the parameter affect the original variable.

Since Java is strictly call by value, even though you cannot directly implement call by reference, you can mimic this behavior by using object references.


Example: Swap Two Numbers (Call by Value)

In this example, we attempt to swap two numbers using a method:

public class Swap {
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
        System.out.println("Inside swap: a = " + a + ", b = " + b);
    }

    public static void main(String[] args) {
        int a = 5;
        int b = 6;
        swap(a, b);
        System.out.println("After swap: a = " + a + ", b = " + b);
    }
}

Output:

Inside swap: a = 6, b = 5
After swap: a = 5, b = 6

Explanation:

  • Inside swap:

    • The swap method receives copies of the values of a and b.

    • It swaps the values of these copies and prints them.

    • The output shows that inside the method, the values have been swapped.

  • After swap:

    • The values of a and b in the main method remain unchanged.

    • This is because Java passed only copies of the values, not references to the original variables.


Visual Explanation: Call by Value

Here's a visual representation of call by value:

  1. Initial Values:

    • a = 5

    • b = 6

  2. Method Call:

    • swap(a, b) is called.

    • Copies of a and b are passed to the swap method.

  3. Inside swap():

    • a = 6 (copy of original b)

    • b = 5 (copy of original a)

  4. Back to main():

    • The original a and b remain unchanged.
Statea (main)b (main)a (swap)b (swap)
Before swap call56--
Inside swap()5665
After swap call56--

Table: Call by Value vs Call by Reference

FeatureCall by ValueCall by Reference
DefinitionPasses a copy of the value of the argument.Passes a reference to the original variable.
Effect on OriginalChanges in the method do not affect the original variable.Changes in the method affect the original variable.
JavaJava uses call by value.Not applicable; Java does not support call by reference.
ExampleSwapping two integers using call by value.Not directly supported in Java.

Additional Notes

  • Call by Value is ideal for immutable types like primitives where you don't want to affect the original data.

  • Call by Reference can be mimicked in Java using object references, where changes to object fields will affect the original object.

This comprehensive explanation covers the concept of call by value in Java and its implications, along with a practical example and visual representation.


7. Factorial of a Number

The factorial of a number ( n ) is the product of all positive integers from 1 to ( n ). It is denoted as ( n! ).

  • Mathematically:
    ( n! = n* (n-1)* (n-2) …..* 1 )

For example:

  • ( 4! = 4 * 3* 2 *1 = 24 )

  • Factorials only exist for positive numbers.


Code: Factorial Calculation

Below is the Java code to calculate the factorial of a number ( n ):

public class Fact {
    public static int fact(int n) {
        int f = 1;
        for (int i = 1; i <= n; i++) {
            f = f * i;
        }
        return f;
    }

    public static void main(String[] args) {
        System.out.println(fact(2));  // Example: Factorial of 2
    }
}

How the Code Works:

  1. fact method:

    • f = 1: This is where the factorial result is stored.

    • The for loop runs from 1 to n and multiplies f with the loop variable i to get the factorial.

    • Finally, the method returns the computed factorial.

  2. Main method:

    • Calls fact(2) to compute the factorial of 2 and prints the result.

Dry Run: Factorial of 2

Dry run refers to a step-by-step walkthrough of the code execution. Let's dry-run the given code for ( n = 2 ).

StepVariableValueExplanation
1n2Input is 2.
2f1Initialize f to 1.
3i1First iteration (i = 1). f = f * i = 1 * 1 = 1
4i2Second iteration (i = 2). f = f * i = 1 * 2 = 2
5i-Loop ends because i exceeds n.
6Return2Return f, which is 2.
7Output2The factorial of 2 is printed: 2.

Output:

2

The factorial of ( 2 ) is correctly computed as ( 2! = 2 ).


8. Function Overloading

Function overloading is the ability to define multiple functions with the same name but different parameter lists.

Example: Function Overloading by Parameters

public class Funct_over {
    public static int Sum(int a, int b) {
        return a + b;
    }

    public static int Sum(int a, int b, int c) {
        return a + b + c;
    }

    public static void main(String[] args) {
        System.out.println(Sum(4, 8));   // Calls the 2-parameter function
        System.out.println(Sum(5, 7, 8)); // Calls the 3-parameter function
    }
}

Output:

12
20

9. Prime Number Check

A prime number is a number that is divisible only by 1 and itself.

Example: Check if a Number is Prime

public class PrimeCheck {
    public static boolean isPrime(int n) {
        if (n <= 1) return false;
        for (int i = 2; i < n; i++) {
            if (n % i == 0) return false;
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println("Is 7 prime? " + isPrime(7));
    }
}

Output:

Is 7 prime? true

Conclusion

Functions (or methods) are the building blocks of reusable and maintainable code. Understanding the syntax, parameters, memory management, and advanced topics like function overloading and recursion is key to mastering Java programming.

By mastering these concepts, you can write efficient, organized, and scalable code in Java. Keep practicing these concepts with various real-world problems to solidify your understanding.


By mastering functions, you’re taking a significant step toward writing clean, maintainable, and efficient Java programs. Stay tuned for more chapters in my Java with DSA series on Hashnode!


Feel free to share this post and leave your feedback!



Connect:

Let’s discuss more about Java and coding! Feel free to leave a comment below or connect with me on LinkedIn.

Thank you for taking the time to read this post! Your interest and feedback help improve the content and make learning more engaging for everyone.