Methods In Java

In Java, a method is a set of instructions that performs a specific task or operation. Methods are defined within a class, and they can be called from other parts of the program to perform their specified tasks. Methods can take input parameters and return values as output, and they are used to encapsulate logic and make it reusable across the program. Methods can also be overloaded, which means that multiple methods can have the same name but different input parameters. This allows for flexibility in the program’s design and functionality. In addition, Java provides a number of built-in methods that can be used for common tasks such as printing output to the console or reading user input. Overall, methods are a fundamental concept in Java programming and are used extensively to create complex, functional programs.

Object State and Methods in OOP

The core concept of OOP is that the object has a

STATE represented by FIELDS (or properties for the languages that support them)

WAY TO MODIFY its state using method calls.

The idea is that methods change the state of the object to which they belong. They can modify other objects’ states, static fields of classes, and so on. But their primary function is to determine a disciplined way to modify an object’s state. So, to oversimplify, the fields represent what the object is, and the methods represent how the object can be modified by other objects or modify itself.

As stated earlier, a Java method is a group of statements that work together to perform an operation. When you use the System.out.println() method, for example, the system executes several statements to display a message on the console.

Look at the following class:

class Lamp {

    //this belongs to the class not a specific object as there is a static keyword
    static int lampCount;
 
    // stores the value for light true if light is on  false if light is off
    boolean isOn;
   
    //stores the voltage at which we can operate the lamp safely
    int operatingVoltage;
   
    //stores the mean life of the lamp in hours
    int meanLife;

    // method to turn on the light
    void turnOn() {
        isOn = true;
        System.out.println("Light on? " + isOn);

    }

    // method to turn off the light
    void turnOff() {
        isOn = false;
        System.out.println("Light on? " + isOn);
    }


    void showLampSpecifications() {
        String spec = "Lamp [isOn=" + isOn + ", operatingVoltage=" + operatingVoltage + ", meanLife=" + meanLife + "]";
        System.out.println(spec);
    }
   
}

Now let us write a Driver class from where we can run the program and test our Lamp class.

class Main {
    public static void main(String[] args) {

        // create objects led and halogen
        Lamp ledLamp = new Lamp();
        Lamp halogenLamp = new Lamp();
       
        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();

  }
}

As usual, we have created two classes. One is for our class and another is to test our class. The lamp is the class of which type of object we want to create. It has 4 fields and 3 methods.

The Lamp class has one static field and three instance variables isOn, operating Voltage and meanLife. The methods are turnOn() - to turn on the lamp, turnOff() - to turn off the lamp and showLampSpecifications() - to show the specifications of the lamp. Now imagine the following scenario.

We know that a class is a blueprint for an object. When we write a class basically we are describing how the JVM should make an object of that type. Suppose we want to create a Lamp type object. How would we do it?

    Lamp ledLamp = new Lamp();

This is how we create an object. Now my friend wants a Lamp too.  And he wants a halogen type lamp. How would we create another? Well, Just like before! We create every object in java in this way(not every object, but you should not worry about that right now or for a while).

    Lamp halogenLamp = new Lamp();

Every time we create an object of some type, in this case Lamp, it can have different instance variables value.

For example, the operatingVoltage value of ledLamp could be 12V(volts), while the operatingVoltage value of halogen could be 20V(volts). Each and every object can have different instance variable values. Look at the following exmaple.

class Lamp {

    //this belongs to the class not a specific object as there is a static keyword

    static int lampCount;

    // stores the value for light true if light is on  false if light is off

    boolean isOn;

    //stores the voltage at which we can operate the lamp safely

    int operatingVoltage;

    //stores the mean life of the lamp in hours

    int meanLife;

    // method to turn on the light

    void turnOn() {

        isOn = true;

        System.out.println("Light on? " + isOn);
        

    }

    // method to turn off the light

    void turnOff() {

        isOn = false;

        System.out.println("Light on? " + isOn);

    }

    void showLampSpecifications() {

        String spec = "Lamp [isOn="+ isOn + ", operatingVoltage=" + operatingVoltage + "V, meanLife=" + meanLife + " hours]";

        System.out.println(spec);

    }

}

class Main {

    public static void main(String[] args) {

        // create objects led and halogen

        Lamp ledLamp = new Lamp();

        Lamp halogenLamp = new Lamp();

        //show lamp spec

        ledLamp.showLampSpecifications();

        halogenLamp.showLampSpecifications();

        System.out.println();//just a blank line to look cool

        //values for instance ledLamp

        ledLamp.isOn = false;

        ledLamp.operatingVoltage = 12;

        ledLamp.meanLife = 20000;

        //values for instance halogenLamp

        halogenLamp.isOn = false;

        halogenLamp.operatingVoltage = 20;

        halogenLamp.meanLife = 25000;

  }

}

Output

Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]
Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]

But what about methods? Is it possible for each object of that type to have a different method behavior?

Well, The answer is yes! Every instance of a given class has the same methods, but they can behave differently depending on the values of the instance variables. The showLampSpecifications() method shows the detailed specification of a lamp, but the instance you call showLampSpecifications() on will show you the detail of that instance. So, if you call showLampSpecifications() on ledLamp it will show you the specifications of the ledLamp instance/object. Or, if you call showLampSpecifications() on halogenLamp it will show you the specifications of the halogenLamp instance/object.

class Lamp {

    //this belongs to the class not a specific object as there is a static keyword

    static int lampCount;

    // stores the value for light true if light is on  false if light is off

    boolean isOn;

    //stores the voltage at which we can operate the lamp safely

    int operatingVoltage;

    //stores the mean life of the lamp in hours

    int meanLife;

    // method to turn on the light

    void turnOn() {

        isOn = true;

        System.out.println("Light on? " + isOn);

    }

    // method to turn off the light

    void turnOff() {

        isOn = false;

        System.out.println("Light on? " + isOn);

    }

    void showLampSpecifications() {

        String spec = "Lamp [isOn=" + isOn + ", operatingVoltage=" + operatingVoltage + "V, meanLife=" + meanLife + " hours]";

        System.out.println(spec);

    }

}

class Main {

    public static void main(String[] args) {

        // create objects led and halogen

        Lamp ledLamp = new Lamp();

        Lamp halogenLamp = new Lamp();

        //show lamp specs

        ledLamp.showLampSpecifications();

        halogenLamp.showLampSpecifications();

        System.out.println();//just a blank line to look cool

        //values for instance ledLamp

        ledLamp.isOn = false;

        ledLamp.operatingVoltage = 12;

        ledLamp.meanLife = 20000;

        //values for instance halogenLamp

        halogenLamp.isOn = false;

        halogenLamp.operatingVoltage = 20;

        halogenLamp.meanLife = 25000;

        //show lamp specs

        ledLamp.showLampSpecifications();

        halogenLamp.showLampSpecifications();

  }

}


Output

Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]
Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]

Lamp [isOn=false, operatingVoltage=12V, meanLife=20000 hours]
Lamp [isOn=false, operatingVoltage=20V, meanLife=25000 hours]

Again, there are two more methods in this Lamp class. Each instance has their own copy. If we call the turnOn() on ledLamp, the ledLamp will turn on. If we call turnOff() on halogenLamp, the halogenLamp will turn off.

class Lamp {
 
    //this belongs to the class not a specific object as there is a static keyword
    static int lampCount;

    // stores the value for light true if light is on  false if light is off
    boolean isOn;
   
    //stores the voltage at which we can operate the lamp safely
   
    int operatingVoltage;
   
    //stores the mean life of the lamp in hours
    int meanLife;

    // method to turn on the light
    void turnOn() {
        isOn = true;
        System.out.println("Light on? " + isOn);

    }

    // method to turn off the light
    void turnOff() {
        isOn = false;
        System.out.println("Light on? " + isOn);
    }


    void showLampSpecifications() {
        String spec = "Lamp [isOn=" + isOn + ", operatingVoltage=" + operatingVoltage + "V, meanLife=" + meanLife + " hours]";
        System.out.println(spec);
    }
   
}

class Main {
    public static void main(String[] args) {

        // create objects led and halogen
        Lamp ledLamp = new Lamp();
        Lamp halogenLamp = new Lamp();
       
        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();
       
        System.out.println();//just a blank line to look cool

        //values for instance ledLamp
        ledLamp.isOn = false;
        ledLamp.operatingVoltage = 12;
        ledLamp.meanLife = 20000;

        //values for instance halogenLamp
        halogenLamp.isOn = false;
        halogenLamp.operatingVoltage = 20;
        halogenLamp.meanLife = 25000;

        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();
        System.out.println();//just a blank line to look cool

        // turn on the light by
        // calling method turnOn()
        ledLamp.turnOn();

        // turn off the light by
        // calling method turnOff()
        halogenLamp.turnOff();

        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();
        System.out.println();//just a blank line to look cool
  }
}

Output

Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]
Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]

Lamp [isOn=false, operatingVoltage=12V, meanLife=20000 hours]
Lamp [isOn=false, operatingVoltage=20V, meanLife=25000 hours]

Light on? true
Light on? false
Lamp [isOn=true, operatingVoltage=12V, meanLife=20000 hours]
Lamp [isOn=false, operatingVoltage=20V, meanLife=25000 hours]

Reflect on the output of this program. Just keep in mind that each instance/object though have the same methods, they can behave differently based on the values of the instance variables.

Method Arguments

You can send things to the method. We have already discussed this in functions. So, we will not bother to discuss it here. Just look at our previous tutorial.

But here’s the important part,

If a method takes a parameter, you must pass it something. And that something must be a value of the appropriate type.

In the following example we are going to add three more methods to our Lamp class so that we can change the variable values using method calls. In a real java application, we use getters and setters methods to get and set the value of the fields of an object, instead of directly accessing the instance variables using the .(dot) operator.

class Lamp {
 
    //this belongs to the class not a specific object as there is a static keyword
    static int lampCount;

    // stores the value for light true if light is on  false if light is off
    boolean isOn;
   
    //stores the voltage at which we can operate the lamp safely
   
    int operatingVoltage;
   
    //stores the mean life of the lamp in hours
    int meanLife;

    // setting the instance variables using methods(setter methods)
    public void setIsOn(boolean isOn) {
        this.isOn = isOn;
    }
    public void setOperatingVoltage(int operatingVoltage) {
        this.operatingVoltage = operatingVoltage;
    }
    public void setMeanLife(int meanLife) {
        this.meanLife = meanLife;
    }
    // method to turn on the light
    void turnOn() {
        isOn = true;
        System.out.println("Light on? " + isOn);

    }

    // method to turn off the light
    void turnOff() {
        isOn = false;
        System.out.println("Light on? " + isOn);
    }


    void showLampSpecifications() {
        String spec = "Lamp [isOn=" + isOn + ", operatingVoltage=" + operatingVoltage + "V, meanLife=" + meanLife + " hours]";
        System.out.println(spec);
    }
   
}

class Main {
    public static void main(String[] args) {

        // create objects led and halogen
        Lamp ledLamp = new Lamp();
        Lamp halogenLamp = new Lamp();
       
        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();
       
        System.out.println();//just a blank line to look cool

        //values for instance ledLamp
        ledLamp.setIsOn(false);
        ledLamp.setOperatingVoltage(12);
        ledLamp.setMeanLife(20000);

        //values for instance halogenLamp
        halogenLamp.setIsOn(true);
        halogenLamp.setOperatingVoltage(20);
        halogenLamp.setMeanLife(25000);

        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();
        System.out.println();//just a blank line to look cool

        // turn on the light by
        // calling method turnOn()
        ledLamp.turnOn();

        // turn off the light by
        // calling method turnOff()
        halogenLamp.turnOff();

        //show lamp spec
        ledLamp.showLampSpecifications();
        halogenLamp.showLampSpecifications();
        System.out.println();//just a blank line to look cool
  }
}

Output:

Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]
Lamp [isOn=false, operatingVoltage=0V, meanLife=0 hours]

Lamp [isOn=false, operatingVoltage=12V, meanLife=20000 hours]
Lamp [isOn=true, operatingVoltage=20V, meanLife=25000 hours]

Light on? true
Light on? false
Lamp [isOn=true, operatingVoltage=12V, meanLife=20000 hours]
Lamp [isOn=false, operatingVoltage=20V, meanLife=25000 hours]

Compare this example with the previous example and try to find out where we made the changes.

In Java, there are basically two techniques for passing parameters. The first is pass-by-reference, and the second is pass-by-value. Java is pass-by-value which means pass-by-copy. First let us give you some good analogy of pass by values and pass by references. Next we will try to realize how these two types

Pass by values scenario: Assume your friend has an external hard drive full of movies. You borrow the hard disk one day and copy all the movies onto your computer. After a few days, your brother deleted the movies or made significant changes to the folder containing the movies. However, changes made to the movies on your desktop have no effect on the movies on your friend's hard disk. The same scenario occurs in pass by value in OOP.
Pass-by reference scenario: Assume you and your colleagues are working on a project report on Google Docs and sharing the same files. Then you can see that changes made by one user are visible to other users, i.e. when you are writing, the same content appears in other users, and if other users make changes to your content, you can see it as well. In summary, when you share a file in Google Docs, changes made in one file by one user affect changes made in other users' files. The same scenario occurs in pass by references in OOP.

Essentially, pass-by-value means that the variable’s actual value is passed.

In the following example, we’ll show how to use pass-by-value, also known as call-by-value, to pass a parameter.

class PassByValue{

    // In the case of call-by-value, the original value of 'num' will remain unchanged.
    int num = 11;

    void call(int num){
         // this local variable 'num' is subject to change in its value
        num = num + 10;
    }

}

public class PassByValueTest{
    public static void main(String[] args) {
        PassByValue value = new PassByValue();
        System.out.println("Before pass by value: " + value.num);

        /*
         * Passing an integer 504 to the call() method. The value of
         * 'num' will still be unchanged since the passing parameter is a
         * primitive type.
         */
        value.call(504);
        System.out.println("After pass by value: " + value.num);
    }
}

We’ve initialized a variable “num” with some value and used the pass-by-value technique to demonstrate how the variable’s value remains unchanged. In the following section, we will attempt to demonstrate a similar example, but this time we will use non-primitives.

Key Facts To Remember

A method uses parameters. A caller passes arguments. Arguments are what you pass into methods. An argument (a value such as 2, “something”, or a reference to a Human object) is thrown face-down into a parameter. A parameter is essentially a local variable. A variable with a type and a name that can be used within the method’s body.

If a method takes a parameter, you must pass it something. And that something must be a value of the appropriate type.

What if the argument you want to pass is an object rather than a primitive one?

You’ll learn more about this in later tutorials, but the answer is already known. Everything in Java is passed by value. Everything. However, value refers to the bits contained within the variable. Remember that variables do not hold objects; they are a remote control—a reference to an object. If you pass a reference to an object into a method, you’re effectively passing a copy of the remote control. But stay tuned; we’ll have a lot more to say about this.

But for now, you can pass an object as an argument to a method like any primitive type. But in this case, you will not pass any value, but the reference to the object itself. We discussed that in the field tutorial. Do not forget that parameters are a kind of variable. So they all obey the same rules. The following program demonstrates how a pass-by-reference works,

class PassByReference {
     
    /*
     *  The original value of 'num' will be changed as we are trying
     *  to pass the objects. Objects are passed by reference.
     */
     
    int num = 10;
    void call(PassByReference reference) {
        reference.num = reference.num+10;
    }
     

}

class PassByReferenceTest{
    public static void main(String[] args) {
 
        PassByReference reference = new PassByReference();
        System.out.println("Before call-by-reference: " + reference.num);
         
        // passing the object as a value using pass-by-reference
        reference.call(reference);
        System.out.println("After call-by-reference: " + reference.num);
         
         
    }
}

Output

Before call-by-reference: 10
After call-by-reference: 20

Do not worry if it still does not make sense to you. It will make more sense to you after a few tutorials. For now just bear with us.

Getting Value From a Method

You can get back values from methods. Method can return values. Every method in java is declared with a return type. To refresh your knowledge on java methods look at our previous tutorial on method. Following example demonstrates getting something from a method. By something we mean value.

class MethodReturn {
 
    // Method 1
    // Since return type of average() method is double
    // so this method should return double value
    double average(double num1, double num2) {
        double average = 0;
        average = (num1 + num2) / 2.0;
       
        // Return statement as we already above have declared
        // return type to be double
        return average;
    }
 
}

class MethodReturnTest{
    // Method 2
    // Main driver method
    public static void main(String[] args) {
        MethodReturn mr = new MethodReturn();
        double averageValue = mr.average(23, 22);
        System.out.println(averageValue);
    }
}

Output

22.5

In this example, the bits representing 22.5 are returned from the average() method and land in the variable called averageValue.

But remember, Whatever method says give back, it must give back. The compiler will not let you return the wrong type of value. You can also return objects. In this case the return type would be the Object type.

Is it possible for a method to declare multiple return values? Or, is it possible to return more than one value?

In a way. A method can declare only one return value. However, if you want to return three int values, the declared return type can be an int array. Put those ints into the array and return it. Returning multiple values of different types is a little more complicated; we’ll cover that in a later tutorial when we discuss ArrayList.

Do I have to return the exact type I declared?

Anything that can implicitly promote that type is returnable. As a result, you can pass an int in place of a double. Caller won’t be concerned because the caller will use the int to fit perfectly into the double while assigning the result. When the specified type is smaller than what you’re attempting to return, an explicit cast must be used.

Do I have to do something with the return value of a method? Can I just ignore it?

You don’t have to acknowledge a return value in Java. Even though you don’t care about the return value, you might want to call a method that has a non-void return type. Instead of calling the method for the results it returns, you are doing the work inside the method in this situation. You are not required to utilize or assign the return value in Java.

RETURN, GETTERS AND SETTERS

Now comes the complicated part.

In Java, return is a reserved keyword. It serves some other purposes in java than just returning a value. It is used to exit from a method, with or without a value. By exiting we mean control flow of the program returning to the code that called the method in the first place.

A method returns to the code that invoked it when it

        completes all the statements in the method,

        reaches a return statement, or

        throws an exception (covered later),

whichever occurs first.

This is what we have learnt so far about “return” – The return type of a method is declared in the method declaration. The return statement is used within the method body to return the value.

Any method that is not declared void must include a return statement and a corresponding return value, as shown below:

    return returnValue;

The data type of the return value must match the method’s declared return type; you can’t return an integer value from a method declared to return a boolean.

But can we use return within the method body if we declare the return type as void? Even if we can, what type of data would we return when we have not specified any return type? In the next section we are going to discuss it.

Any method declared void doesn’t return a value. It is not required to include a return statement, but it may. In this case, a return statement can be used to exit the method by branching out of a control flow block as follows:

    return;

Yes, just “return” followed by a semicolon(;) to mark the end of the statement. That’s it.

class Return1 {

    void demoMethod(){

        boolean t = true;
        System.out.println("Before the return.");

        if(t) return;  // return to caller
        System.out.println("This won't execute.");

    }

    public static void main(String args[]){

        Return1 r1 = new Return1();
        r1.demoMethod();

    }

}

You can only use return, without any expression following it, in a void method. It serves as the method’s immediate termination point. It is mostly used in early termination branches that bypass a method’s main logic.

There are some cool things you can do with parameters and return types. It’s time to show you how to use Getters and Setters in Java. Though you have already been introduced with getter methods and setter methods tag along. This may be your first step towards real OO.

Getters and Setters let you, well, get and set things. Instance variable values, usually.

In Java, getters and setters are methods that allow us to read and write the value of an object’s instance variables. And this is how we set and get values rather than directly accessing class fields with dot(.) operator. We can achieve the one pillar of OOPs, encapsulation, by using getter and setter. In the very next tutorial we will discuss encapsulation. In this tutorial let us just know how to use them.

class User {  
    int userId;
    String userName;    

    int getUserId(){
        return userId;
    }
    void setUserId(int uid){
        userId = uid;
    }

    String getUserName() {  
        return userName;  
    }  
    void setUserName(String name) {  
        userName = name;  
    }  
   
}

class Main{
    public static void main(String[] args) {
       
        User user1 = new User();
        user1.setUserId(1);
        user1.setUserName("John Doe");
        System.out.println("User1 Id: " + user1.getUserId() + ", User1 Name: " + user1.getUserName());

        User user2 = new User();
        user2.setUserId(2);
        user2.setUserName("John Wick");
        System.out.println("User2 Id: " + user2.getUserId() + ", User2 Name: " + user2.getUserName());
       
    }
}

Run this program in the Console and try to understand what is going on under the hood.

Share The Tutorial With Your Friends
Twiter
Facebook
LinkedIn
Email
WhatsApp
Skype
Reddit

Check Our Ebook for This Online Course

Advanced topics are covered in this ebook with many practical examples.