How do getters and setters work?

Learn how do getters and setters work? with practical examples, diagrams, and best practices. Covers java, setter, getter development techniques with visual explanations.

Understanding Getters and Setters: Encapsulation in Object-Oriented Programming

Hero image for How do getters and setters work?

Explore the fundamental concepts of getters and setters in object-oriented programming, their role in encapsulation, and how they enhance data control and maintainability.

In object-oriented programming (OOP), encapsulation is a core principle that bundles data (attributes) and methods (functions) that operate on the data within a single unit, typically a class. It also restricts direct access to some of the object's components, preventing external code from directly manipulating internal data. Getters and setters are special methods that provide controlled access to an object's private attributes, serving as the gatekeepers for data manipulation.

What are Getters and Setters?

Getters (also known as accessors) are methods used to retrieve the value of a private variable. They allow external code to read the state of an object without directly exposing its internal representation. Setters (also known as mutators) are methods used to modify the value of a private variable. They provide a controlled way to update an object's state, often including validation logic to ensure data integrity.

classDiagram
    class Person {
        -String name
        -int age
        +String getName()
        +void setName(String name)
        +int getAge()
        +void setAge(int age)
    }
    Person --> getName
    Person --> setName
    Person --> getAge
    Person --> setAge

Class diagram illustrating a 'Person' class with private attributes and public getter/setter methods.

The primary purpose of using getters and setters is to enforce encapsulation. By making attributes private and providing public methods to access and modify them, you gain several advantages:

1. Data Validation

Setters can include logic to validate input before assigning it to an attribute, ensuring that the object's state remains consistent and valid. For example, a setAge method could check if the provided age is a positive number.

2. Controlled Access

You can control how and when attributes are accessed or modified. For instance, an attribute might only have a getter (read-only) but no setter, making it immutable after initialization.

3. Flexibility and Maintainability

The internal representation of an object can change without affecting external code that uses its public getter/setter methods. If you decide to store an attribute differently (e.g., combine first and last name into a single fullName attribute), you only need to update the getter and setter methods, not every piece of code that uses the attribute.

4. Debugging

By centralizing data access through methods, it becomes easier to debug issues related to incorrect data modification. You can place breakpoints within setters to see exactly when and how an attribute's value changes.

Implementing Getters and Setters in Java

In Java, getters and setters are typically implemented as public methods following a common naming convention: get<PropertyName>() for getters and set<PropertyName>(value) for setters. The attributes themselves are usually declared as private.

public class Employee {
    private String name;
    private double salary;

    // Getter for name
    public String getName() {
        return name;
    }

    // Setter for name
    public void setName(String name) {
        if (name != null && !name.trim().isEmpty()) {
            this.name = name;
        } else {
            System.out.println("Name cannot be empty.");
        }
    }

    // Getter for salary
    public double getSalary() {
        return salary;
    }

    // Setter for salary with validation
    public void setSalary(double salary) {
        if (salary >= 0) {
            this.salary = salary;
        } else {
            System.out.println("Salary cannot be negative.");
        }
    }

    public static void main(String[] args) {
        Employee emp = new Employee();
        emp.setName("Alice");
        emp.setSalary(50000.0);

        System.out.println("Employee Name: " + emp.getName());
        System.out.println("Employee Salary: " + emp.getSalary());

        // Attempt to set invalid data
        emp.setName("");
        emp.setSalary(-100.0);
    }
}

When to Use and When to Avoid Getters and Setters

While getters and setters are powerful tools for encapsulation, it's important to use them judiciously. Overuse can sometimes lead to 'anemic domain models' where objects are just data holders with no behavior, and business logic resides outside the objects. This can defeat some of the benefits of OOP.

flowchart TD
    A[Start]
    A --> B{Need to expose internal state?}
    B -->|Yes| C{Is direct access safe/necessary?}
    C -->|Yes| D[Consider public field (rare)]
    C -->|No| E[Use Getter]
    B -->|No| F{Need to modify internal state?}
    F -->|Yes| G{Is direct modification safe/necessary?}
    G -->|Yes| H[Consider public field (rare)]
    G -->|No| I[Use Setter (with validation)]
    F -->|No| J[Keep private, no access]
    D --> K[End]
    E --> K[End]
    H --> K[End]
    I --> K[End]
    J --> K[End]

Decision flow for using getters and setters versus direct field access.

Consider using getters and setters when:

  • You need to enforce data validation or business rules when an attribute is set.
  • You want to provide read-only access to an attribute (getter only).
  • You anticipate that the internal representation of the data might change in the future.
  • You need to perform additional actions (e.g., logging, event triggering) when an attribute is accessed or modified.

Avoid them when:

  • The attribute is truly internal and doesn't need to be exposed to the outside world at all.
  • The object should perform actions on its own data rather than just exposing it for external manipulation (favoring behavior over just data access).
  • You are creating immutable objects, where all attributes are set during construction and never changed afterward.