SyntaxStudy
Sign Up
Java Class Design: Constructors, Fields, and Getters/Setters
Java Beginner 1 min read

Class Design: Constructors, Fields, and Getters/Setters

A class is a blueprint for creating objects. It defines the state (fields) and behaviour (methods) that every instance will have. Constructors are special methods with the same name as the class and no return type; they are called when an object is created with new. A class can have multiple constructors (constructor overloading), and one constructor can call another using this(...). Instance fields represent the state of each object. They should almost always be private to enforce encapsulation. Getters (also called accessors) are public methods that return the value of a field. Setters (mutators) are public methods that update a field, usually with validation. If a field should never change after construction, declare it final and provide only a getter. Static fields belong to the class rather than to any instance. A static field has exactly one copy regardless of how many objects are created. Static fields are commonly used for constants (static final) or for tracking class-level state such as a count of instances. Static methods cannot access instance fields directly because they are not associated with any particular object.
Example
public class Employee {

    // Class-level: tracks total instance count
    private static int instanceCount = 0;

    // Instance fields
    private final int    id;          // assigned at construction, never changes
    private       String name;
    private       String department;
    private       double salary;

    // Primary constructor
    public Employee(String name, String department, double salary) {
        if (salary < 0) throw new IllegalArgumentException("Salary cannot be negative");
        this.id         = ++instanceCount;
        this.name       = name;
        this.department = department;
        this.salary     = salary;
    }

    // Delegating constructor (calls primary constructor)
    public Employee(String name, String department) {
        this(name, department, 0.0); // new hire with no salary yet
    }

    // Static factory method (named constructor)
    public static Employee intern(String name) {
        return new Employee(name, "Internship", 15.0);
    }

    // Getters
    public int    getId()         { return id; }
    public String getName()       { return name; }
    public String getDepartment() { return department; }
    public double getSalary()     { return salary; }

    // Setters with validation
    public void setName(String name) {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required");
        this.name = name;
    }
    public void setSalary(double salary) {
        if (salary < 0) throw new IllegalArgumentException("Salary cannot be negative");
        this.salary = salary;
    }

    // Static getter for class-level field
    public static int getInstanceCount() { return instanceCount; }

    @Override public String toString() {
        return String.format("Employee{id=%d, name='%s', dept='%s', salary=%.2f}",
            id, name, department, salary);
    }

    public static void main(String[] args) {
        Employee e1 = new Employee("Alice", "Engineering", 90_000);
        Employee e2 = new Employee("Bob", "Marketing");
        Employee e3 = Employee.intern("Carol");

        System.out.println(e1);
        System.out.println(e2);
        System.out.println(e3);
        System.out.println("Total employees created: " + Employee.getInstanceCount());

        e2.setSalary(65_000);
        System.out.println("After salary update: " + e2);
    }
}