Java OOP: Class Methods Tutorial

In this Java tutorial we learn how to group sections of program functionality into smaller reusable units called methods.

We cover how to define and use non-static and static methods, how to add parameters and how to return values, along with control, from them. We also cover the 'this' construct and how it refers to the calling object as well as how to construct objects with initial values.

Lastly, we quickly discuss and link to the Lambdas lesson and do a quick little challenge.

Here's a table of contents of what you'll learn in this lesson:
(click on a link to skip to its section)

Let's jump right in.

What is a method

Methods allow us to group sections of our code into a smaller, reusable units.

As an example, let’s consider some simple logic.

Example:
public class Program {
    public static void main(String[] args) {

        // number to check
        int num = 5;

        // if the number can be divided by two
        // without a remainder, it's an even num
        if (num % 2 == 0) {
            System.out.println(num + " is an even number");
        } else {
            System.out.println(num + " is an odd number");
        }
    }
}

The simple logic in the example above will check if a number is even or odd.

Our application may require this evaluation multiple times throughout the code. We don’t want to repeat ourselves and retype this logic each time we want to check a number.

Instead, we want to separate the logic into a unit that we can more easily use over and over, anywhere in our code. These units are called methods.

How to define a method in Java

A method definition consists of the following parts.

  • An access modifier
  • A return type
  • A name
  • Parameters (optional)
  • A body with one or more statements
  • A returned value (optional)

In Java, methods can only be defined in classes, we cannot define standalone methods.

Syntax:
class class_name {

    access_modifier return_type method_name(parameter_type parameter) {

        // method body with one
        // or more statements

        return value;
    }
}

We’ll start with the most basic method and add features as we go.

Example:
public class Program {
    public static void main(String[] args) {}
}

class Logger {

    // method definition
    public void logMessage() {

        System.out.println("Hello from inside a method");
    }
}

In the example above, we create a class called ‘Logger’ with a method inside called ‘logMessage’. All it does is print some text to the console.

Typically we would create each class in its own file, but to keep things simple, we just defined the ‘Logger’ class below the ‘Program’ class.

Let’s break down the method definition step by step.

  1. For the access modifier, we used public to allow access to the function from any other class. We cover access modifiers in detail in the OOP: Encapsulation & Access Modifiers lessonOpens up in a new page .
  2. For the return type, we used void. When a function doesn’t return a value, we always specify the return type as void.
  3. Our method has no parameters so we left the parameter list empty. The parentheses must always be included even if the method doesn’t have any parameters.
  4. In the function body we just print some text to the console.
  5. Because our function doesn’t return anything, we can omit the return keyword.

Now if we go ahead and run the script, nothing happens. That’s because we’ve defined the method, but we haven’t used anywhere it yet.

How to use (invoke/call) a method in Java

To use a method, we need to tell the compiler that we want the method to execute the code in its body once. We do this by invoking the method, otherwise known as calling it.

To call a method we write its name, its parameter list and terminate the statement with a semicolon.

But, because the method is inside a class, we need to instantiate an object and call the method through dot notation. Like we did with parameters.

Syntax:
class class_name {

    // method definition
    access_modifier return_type method_name() {
        // method body
    }
}

// object instantiation
class_name object_name = new class_name();

// method call
object_name.method_name();
Example:
public class Program {
    public static void main(String[] args) {

        // instantiate object
        Logger log1 = new Logger();

        // invoke method through
        // dot notation
        log1.logMessage();
    }
}

class Logger {

    // method definition
    public void logMessage() {

        System.out.println("Hello from inside a method");
    }
}

This time, when we compile and run the script, the text is printed to the console.

Even though we don’t have any parameters, and therefore don’t need any arguments, we still need to add the parentheses in the both the definition and the call.

How to add parameters to a method in Java

At this point our method isn’t very useful, it only prints predefined text to the console. With parameters we can change it so that the method prints any message we want.

A parameter is simply a temporary variable that we can use inside the body of the method. The compiler will replace every occurance of the parameter in the definition, with whatever we specify as an argument in the call.

Syntax:
// definition
access_modifier return_type method_name(x_type x) {

    // use x here
}

// call
name(value_to_replace_x);

We’ll use our simple log method again.

Example:
public class Program {
    public static void main(String[] args) {

        // instantiate object
        Logger log1 = new Logger();

        // method now requires an
        // argument between the
        // parentheses to match
        // the parameter in the
        // method definition
        log1.logMessage("Hello, World!");
    }
}

class Logger {

    public void logMessage(String msg) {

        System.out.println(msg);
    }
}

This time, we’ve added the parameter ‘msg’ of type String in the method’s parameter list. Then, we referred to ‘msg’ where we wanted the value of ‘msg’ to go in the body.

In the method call, we specify the words some text as the argument. Every instance of the ‘msg’ parameter in the body will be replaced by whatever we type here.

From the output we can see that the method printed the text we typed as an argument.

Output:
 Hello, World!

We can also call the method as many times as we want with different messages.

As an example, let’s call the method a few more times with different messages as the argument.

Example:
public class Program {
    public static void main(String[] args) {

        // instantiate object
        Logger log1 = new Logger();

        // multiple calls
        log1.logMessage("Hello there");
        log1.logMessage("");
        log1.logMessage("General Kenobi");
        log1.logMessage("You are a bold one...");
    }
}

class Logger {

    public void logMessage(String msg) {

        System.out.println(msg);
    }
}

When we run the example above, all the messages are printed to the screen, even the one with an empty string.

Output:
Hello there

General Kenobi
You are a bold one...

Java also allows us to add multiple parameters to our methods. If we have multiple parameters, we separate them with commas, both in the definition and the call.

Example:
public class Program {
    public static void main(String[] args) {

        // instantiate object
        Logger log1 = new Logger();

        // multiple arguments
        log1.logName("James", "Bond");
    }
}

class Logger {

    // multiple parameters
    public void logName(String fname, String lname) {

        System.out.println(lname + ", " + fname + " " + lname);
    }
}

How to return a value from a method in Java

Methods can return a value to the caller when we invoke them.

As an example, let’s consider a simple math method that adds two numbers together. We may not want to print that value to the page directly from inside the method, but use it for other calculations somewhere else in our application.

We can return the value from the method and either use it directly, or store it in a data container for later use.

To return a value, we write the return keyword, followed by the value we want to return and a semicolon to terminate the statement. We also have to specify the type of value returned in front of the method name in the definition.

Syntax:
access_modifier return_type method_name(parameter_type parameter) {

    // method body

    return value;
}
Example:
public class Program {
    public static void main(String[] args) {

        // instantiate object
        SimpleMath sm1 = new SimpleMath();

        // catch the returned value
        // in a data container
        int result = sm1.addInt(5, 3);

        // or use it directly
        System.out.println( sm1.addInt(5, 3) );
    }
}

class SimpleMath {

    // returns a value of int type
    public int addInt(int num1, int num2) {

        // return the result of the
        // addition with the return
        // keyword
        return num1 + num2;
    }
}

The example above will add ‘num2’ to ‘num1’, and return the result when the method is called.

We call the method twice here to demonstrate that it can be used directly in something like the println() method, or we can assign the returned value to a variable to store it.

Static methods in Java

A static class method is a method that belongs to the class itself, not the instance object of a class.

That means we don’t need an object to call a static class method. We call them directly from the class itself.

To mark a method as static, we simply add the static keyword between the access modifier and the return type.

Syntax:
access_modifier static return_type method_name() {

    // body
}
Example:
public class Program {
    public static void main(String[] args) {}
}

class Logger {

    // static method
    public static void logMessage(String msg) {
        System.out.println(msg);
    }
}

Now that the method has been marked as static, we can use it without the need to instantiate a class object first.

Syntax:
// definition
class class_name {

    access_modifier static return_type method_name(parameters) {
        // body
    }
}

// call
class_name.method_name();
Example:
public class Program {
    public static void main(String[] args) {

        // invoke method directly
        // from the class, using
        // the class name instead
        // of an object name
        Logger.logMessage("Hello");
    }
}

class Logger {

    // static method
    public static void logMessage(String msg) {
        System.out.println(msg);
    }
}

In the example above, we invoke the method directly by using the class name instead of an object with dot notation.

Lambda expressions (anonymous methods) in Java

Lambda expressions always have to be assigned to a reference type of Functional Interfaces.

We cover lambda expressions in the OOP: Lambda Expressions lessonOpens up in a new page , after we learn about interfaces.

Mini challenge

Now that we know more about methods, try to convert the following logic (from the start of the tutorial) into a method.

Logic:
public class Program {
    public static void main(String[] args) {

        // number to check
        int num = 5;

        // if the number can be divided by two
        // without a remainder, it's an even num
        if (num % 2 == 0) {
            System.out.println(num + " is an even number");
        } else {
            System.out.println(num + " is an odd number");
        }
    }
}

If you get stuck, see our solutions below.

Solution:
public class Program {
    public static void main(String[] args) {

    // method that prints directly
    isOdd(5);
    isOdd(-127);

    // method that returns value
    boolean result = isEven(598);
        if(result) {
            System.out.println("Number returned is even");
        }
    }

    // checks if a number is even or odd
    // prints directly to the console
    public static void isOdd(int num) {

        if (num % 2 == 0) {
            System.out.println(num + " is an even number");
        } else {
            System.out.println(num + " is an odd number");
        }
    }

    // checks if number is even or odd
    // returns true if even, false if odd
    public static boolean isEven(int num) {

        if (num % 2 == 0) {
            return true;
        }

        return false;
    }
}

The ‘this’ construct in Java

The this construct is used inside a class to refer to the object that is currently calling it.

As an example, let’s consider the following class.

Example:
public class Program {
    public static void main(String[] args) {

        Person p1 = new Person();

        p1.name = "John";
        p1.greeting(p1.name);
    }
}

class Person {

    public String name = "Unknown";

    public void greeting(String userName) {

        System.out.println("Hi, my name is " + userName);
    }
}

The ‘greeting’ method’s purpose is to greet a person by their name. When we call the method, it will print ‘Hi, my name is John’ to the console.

The method is doing what it’s supposed to, provided that the programmer passed the correct name as an argument.

If the programmer were to make a mistake and enter something else as the value, the method would no longer function as intended.

Example:
public class Program {
    public static void main(String[] args) {

        Person p1 = new Person();

        p1.name = "John";
        p1.greeting("Jane");
    }
}

class Person {

    public String name = "Unknown";

    public void greeting(String userName) {

        System.out.println("Hi, my name is " + userName);
    }
}

In the example above, the method will print the name Jane, instead of John, which is not what we want.

To fix this problem, Java provides us with the this construct, which is used to refer to the object that’s calling the method.

To use the construct, we write the keyword this , followed by the dot operator and a class member name.

Syntax:
this.property
// or
this.method()
Example:
public class Program {
    public static void main(String[] args) {

        // person 1
        Person p1 = new Person();
        p1.name = "John";
        p1.greeting();

        // person 2
        Person p2 = new Person();
        p2.name = "Jane";
        p2.greeting();
    }
}

class Person {

    public String name = "Unknown";

    public void greeting() {

        System.out.println("Hi, my name is " + this.name);
    }
}

We replaced the ‘userName’ parameter in the method with this.name and when we run the example above, it will print the correct name each time the method is called.

Output:
Hi, my name is John
Hi, my name is Jane

Essentially, what’s happening is that Java is replacing the ‘this’ keyword with whatever the object’s name is.

The programmer can no longer make a mistake by entering the wrong name. The compiler will always use the name that’s been assigned to the object.

It makes our code shorter, easier to read and less prone to errors and vulnerabilities.

How to construct an object with values in Java

When we create an instance object of a class, we usualy need to set the attribute values to custom values before we can effectively use them.

We can create and initialize an object in one step with a constructor method. A constructor method will construct the object by assigning values to the attributes when the object is created.

A constructor method has the same name as the class it’s in and doesn’t include a return type.

Syntax:
class class_name {

    // constructor
    class_name() {

    }
}
Example:
public class Program {

    public static void main(String[] args) {}
}


class Employee {

    // properties
    String name = "Unknown";

    // constructor method
    Employee() {

    }
}

When an object is created from the class, the constructor method will run.

Inside the constructor method we can initialize properties with values.

Example:
public class Program {

    public static void main(String[] args) {

        Employee emp1 = new Employee();

        System.out.println(emp1.name);
    }
}


class Employee {

    // properties
    String name = "Unknown";

    // constructor method
    Employee() {

        this.name = "John";
    }
}

In the example above, we specify that the ‘name’ property should be initialized with John whenever we create a new object.

Just like a regular method, Java allows us to accept parameters in the constructor method.

Example:
public class Program {

    public static void main(String[] args) {

        Employee emp1 = new Employee("John");
        System.out.println(emp1.name);

        Employee emp2 = new Employee("Jane");
        System.out.println(emp2.name);
    }
}


class Employee {

    // properties
    String name = "Unknown";

    // constructor method
    Employee(String fullName) {

        this.name = fullName;
    }
}

If a constructor has parameters, we have to pass arguments to it when the object is created, otherwise the compiler will raise an error that the constructor is undefined.

Summary: Points to remember

  • Methods group our logic code into smaller reusable units, and are usually responsible for only a single specific task.
  • It’s not enough for a method to be defined, we must call (invoke) it in order to use it.
  • Methods can accept one or more parameters that allow different inputs to be used on each call of the method.
  • Methods can return a single value with the return keyword.
  • We do not need an instance of a class to invoke a static method.
  • The this construct refers to the calling object. It’s essentially a temporary variable that is replaced with the object name to refer to itself.
    • Java doesn’t require us to use it, but it’s considered good practice to always be as explicit as possible to help avoid errors and vulnerabilities.
  • A constructor method will initialize class properties with any values we specify.
    • A constructor method has the same name as the class, no return type and may accept parameters.
    • A constructor method is automatically called when a new object is created.