Getters and Setters in Java

Naveen AnamaneniUpdated · 5 min read

Once a field is private, outside code needs a polite way to ask for its value, or to request a change. A getter is a method that returns a field's value; a setter is a method that changes it, after checking that the new value makes sense. They look like boilerplate, but they're where encapsulation actually happens: the setter is the checkpoint, and the getter decides what the outside world gets to see.

A Student with Rules

Students.java▶ Try it
import java.util.ArrayList;
import java.util.List;
 
public class Students {
    static class Student {
        private final String rollNo;
        private String name;
        private int marks;
        private boolean active = true;
        private final List<String> subjects = new ArrayList<>();
 
        Student(String rollNo, String name) {
            this.rollNo = rollNo;
            setName(name);
        }
 
        public String getRollNo() { return rollNo; }
 
        public String getName() { return name; }
 
        public void setName(String name) {
            if (name == null || name.isBlank()) {
                throw new IllegalArgumentException("Name is required");
            }
            this.name = name.strip();
        }
 
        public int getMarks() { return marks; }
 
        public void setMarks(int marks) {
            if (marks < 0 || marks > 100) {
                throw new IllegalArgumentException(
                    "Marks must be 0 to 100, got " + marks);
            }
            this.marks = marks;
        }
 
        public boolean isActive() { return active; }
        public void setActive(boolean active) { this.active = active; }
 
        public List<String> getSubjects() { return List.copyOf(subjects); }
        public void addSubject(String subject) { subjects.add(subject); }
    }
 
    public static void main(String[] args) {
        Student s = new Student("R-17", "  Advitha ");
        s.setMarks(88);
        s.addSubject("Physics");
        System.out.println(s.getRollNo() + " " + s.getName()
            + ": " + s.getMarks());
        try {
            s.setMarks(120);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
        try {
            s.getSubjects().add("Gaming");
        } catch (UnsupportedOperationException e) {
            System.out.println("Subjects can't be changed from outside");
        }
        System.out.println(s.getSubjects() + ", active: " + s.isActive());
    }
}
Output
R-17 Advitha: 88
Marks must be 0 to 100, got 120
Subjects can't be changed from outside
[Physics], active: true

How it works

  1. rollNo is final with only a getter: read-only after construction.
  2. setName cleans the input (strip() removes the spaces) and refuses blanks. The constructor calls it too, so the rule applies from the start.
  3. setMarks rejects 120. The object keeps its valid 88.
  4. The boolean getter is named isActive(), not getActive().
  5. getSubjects() returns List.copyOf(subjects), an unmodifiable copy. Adding to it throws, so the internal list is safe. Subjects are changed only through addSubject.

Try it yourself: add a removeSubject(String) method, and a setter rule that a student can't be made inactive while their marks are above 90 (an unusual rule, but it shows where rules live).

Naming Rules

FieldGetterSetter
String namegetName()setName(String name)
int marksgetMarks()setMarks(int marks)
boolean activeisActive()setActive(boolean active)
final String rollNogetRollNo()none

These names follow the JavaBeans convention. Frameworks such as Spring, Hibernate and Jackson look for exactly these names to read and write your objects, so stick to them.

Should Every Field Get a Setter?

No. Add a setter only when outside code genuinely needs to change that value directly. Often a method that names the action is better:

Instead ofPrefer
setBalance(getBalance() + 500)deposit(500)
setStatus("SHIPPED")ship()
setCount(getCount() + 1)increment()

Action methods keep the rules inside the class; a setter often pushes the logic out to callers.

Common Mistakes

Setters with no validation. Then a private field is no safer than a public one.

Returning internal lists, arrays or Date objects directly. Callers can change them behind the object's back. Return copies or unmodifiable views.

getActive() for a boolean, or setname with a lowercase letter. Frameworks won't recognize them.

Interview Corner

Why use getters and setters instead of public fields?

They keep fields private, so the class controls access. Setters can validate and normalize values, getters can return copies or computed values, either can be left out to make a field read-only or write-only, and the internal representation can change without changing callers. Frameworks also rely on the getter and setter naming convention.

How do you make a field read-only?

Make it private (and usually final), set it in the constructor, and provide a getter but no setter. If the field refers to a mutable object, the getter should return a copy or an unmodifiable view.

Practice

  1. Easy: Write a Product class with name, price and inStock, with getters, setters, and a rule that the price can't be negative.
  2. Harder: Write a Playlist class with a private List<String> songs. Provide getSongs() that can't be used to modify the list, and addSong that refuses duplicates.

Quick check: Getters and setters

4 questions
1What is the conventional getter for boolean active?
2Where should validation of a new value go?
3How do you make rollNo read-only?
4Why return List.copyOf(subjects) from a getter?

Key Takeaways

Was this tutorial helpful?

Lesson 142 of 482