Get up to 80 % extra points for free! More info:

Lesson 10 - Getters and setters in Java

In the previous exercise, Solved tasks for OOP in Java lesson 9, we've practiced our knowledge from previous lessons.

In the previous lesson, Solved tasks for OOP in Java lesson 9, we learned about static class members in Java. In today's tutorial, we're going to look at getter and setter methods.

Getters and setters

We often want to have control over how an object field is being changed from outside of the class. We'd like to set the field as read-only or react to its changes somehow. Let's create a new project (name it GetSet) and add the following Student class which will represent a student in a database.

public class Student {
    public String name;
    public boolean male;
    public int age;
    public boolean fullAged;

    public Student(String name, boolean male, int age) {
        this.name = name;
        this.male = male;
        this.age = age;
        fullAged = true;
        if (age < 18) {
            fullAged = false;
        }
    }

    @Override
    public String toString() {
        String iAmFullAged = "I'm";
        if (!fullAged) {
            iAmFullAged = "I'm not";
        }
        String gender = "male";
        if (!male) {
            gender = "female";
        }
        return String.format("I'm %s, %s. I'm %d years old and %s of age.", name, gender, age, iAmFullAged);
    }

}

The class is very simple, the student has a name, gender, and age. The fullAged field is set according to the age and provides a more comfortable determination whether the student is of age from different places in the system. We use a boolean value to store the gender, true indicates that he's male. The constructor will determine whether the student is of age or not. The toString() method has been altered to suit our needs. In a real world situation, it'd probably just return the student's name. Let's create a student using the constructor:

Student s = new Student("Peter Brown", true, 20);
System.out.println(s);

The output:

Console application
I'm Peter Brown, male. I'm 20 years old and I'm of age.

Everything looks nice, but the fields can be re-written. We can break the object like this, so it'll no longer function properly (i.e. would have an inconsistent internal state):

Student s = new Student("Peter Brown", true, 20);
s.age = 15;
s.male = false;
System.out.println(s);

The output:

Console application
I'm Peter Brown, female. I'm 15 years old and I'm of age.

Certainly, we would want fullAged to be updated when the age is changed. Aside from that, there is no need to allow e.g. a gender to be changed. However, we want to keep the properties accessible for reading, so we can't make them private. In earlier lessons of our course, we've used get methods to read private fields. We would name them something like getAge() and so on. In Java, we declare all the fields which should be accessible from the outside as private and we implement similar methods to make them accessible. We name them as getFieldName() for reading and setFieldName() for writing. For boolean fields, we usually name getters as isFieldName(). The class would now look something like this:

public class Student {
    private String name;
    private boolean male;
    private int age;
    private boolean fullAged;

    public Student(String name, boolean male, int age) {
        this.name = name;
        this.male = male;
        setAge(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMale() {
        return male;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        // updating whether student is of age
        fullAged = true;
        if (age < 18) {
            fullAged = false;
        }
    }

    public boolean isFullAged() {
        return fullAged;
    }

    @Override
    public String toString() {
        String iAmFullAged = "I'm";
        if (!fullAged) {
            iAmFullAged = "I'm not";
        }
        String gender = "male";
        if (!male) {
            gender = "female";
        }
        return String.format("I'm %s, %s. I'm %d years old and %s of age.", name, gender, age, iAmFullAged);
    }

}

The methods just returning a value are very simple. In the method setting the age is some more logic, since we have to reconsider the fullAged field. We made sure we can't set variables in any other way than what we want. We now control all the field changes and can work with them as needed. Our design must prevent all unwanted changes of the internal state that would cause an object to malfunction. Notice the change in the constructor where we set the age using the setAge() method.

Methods for returning values are called getters and methods for setting values are called setters. We could potentially add an editStudent() method to edit the other fields sort of like the constructor. Essentially, the student's name, age, and other fields would be updated using this method. We could also validate the values being set there since we would be able to handle all attempts to change certain values in one place.

The question now is, what are the benefits of the name field being private when we can both write it and read it? We now got 2 methods for accessing it which only occupies place in the code. And isn't it also slower?

We really wrote that right, or at least as Java programmers usually do that. Java performs many optimizations before compiling so if the methods are as simple they only return a value, the method is compiled as a direct access to the memory. SO they are as fast as we used plain attributes (considering there is no other logic in the getter).

IDE (NetBeans) can generate getters and setters automatically for us, there is no need to write them over and over again. The only this we need to do is to click on the variable with the right mouse button and choose Redactor -> Encapsulate fields.

Generating getters and setters in NetBeans automatically - Object-Oriented Programming in Java

In the next dialog, we specify for which fields we want to generate getters and setters for. We won't generate setters for fullyAged and male fields, making them read-only. There is no sense in changing the gender at all (if really needed, there would be some special method to avoid doing that accidentally). We confirm the dialog.

Encapsulating fields in NetBeans automatically - Object-Oriented Programming in Java

Compiler optimizations solved the performance issue which would be caused by calling the methods otherwise. We also bypassed manual writing methods manually by generating them automatically. The question still is, what are the benefits?

The main reason is some kind of standardization. We don't have to think about whether the property we want to access has a getter or it's a public field, we just always call the method starting with get* on the instance, resp. set* if we want to change it.

Another benefit is that we can decide later that we want to make some field as read-only, we just remove the setter. We don't have to create a getter and change the field access modifier, which would change the class interface and break existing code using it.

From now on, we'll generate getters and setters for all fields which should be accessible from the outside. There will be almost no public fields in our classes anymore.

Let's try the code that broke the object's inner state once more:

Student s = new Student("Peter Brown", true, 20);
s.setAge(15);
// s.setMale(false); // This line has to be commented out since it's no longer possible to change the gender
System.out.println(s);

And the output is correct now:

Console application
I'm Peter Brown, male. I'm 15 years old and I'm not of age.

In the next lesson, ArrayList in Java, we'll learn about lists in Java.


 

Previous article
Solved tasks for OOP in Java lesson 9
All articles in this section
Object-Oriented Programming in Java
Skip article
(not recommended)
ArrayList in Java
Article has been written for you by David Capka Hartinger
Avatar
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities