Encapsulation, Constructors, and Access Control in Java OOP

Programming principles like high cohesion and low coupling encourage self-contained class internals while exposing only minimal public interfaces. Encapsulation implements this by restricting direct state manipulation and using controlled methods for access and mutation.

A common scenario arises when validating field assignments. For example, a Creature class with a limbCount field should reject negative or odd values. Without encapsulation, callers could assign creature.limbCount = -3 directly. Marking the field private prevents this, and a setter enforces validation:

public class Creature {
    private int limbCount;

    public void setLimbCount(int count) {
        if (count >= 0 && count % 2 == 0) {
            this.limbCount = count;
        } else {
            this.limbCount = 0;
        }
    }

    public int getLimbCount() {
        return limbCount;
    }
}

Java's access modifiers control visibility:

  • private — accessible only within the same class
  • default (no modifier) — accessible within the same package
  • protected — accessible with in the same package plus subclasses
  • public — accessible everywhere

These modifiers apply to fields, methods, constructors, and inner classes. For top-level classes, only public and default are allowed.

package domain;

public class Invoice {
    private int invoiceId;       // restricted
    double totalAmount;          // package-private
    public String customerName;  // fully accessible

    private void validate() { }
    void prepare() { }
    public void submit() { }
}

A JavaBean encapsulates state with a public no-argument constructor and getter/setter pairs:

public class Employee {
    private int id;
    private String fullName;

    public Employee() { }

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getFullName() { return fullName; }
    public void setFullName(String fullName) { this.fullName = fullName; }
}

Constructors initialize objects. When no constructor is written, the compiler supplies a default no-argument version. Once you define any constructor, that default disappears. Overloading allows multiple initialization paths:

public class Vehicle {
    String model;
    int year;

    public Vehicle() {
        System.out.println("Default constructor");
    }

    public Vehicle(String model) {
        this.model = model;
    }

    public Vehicle(String model, int year) {
        this(model);   // delegates to the single-parameter constructor
        this.year = year;
    }
}

Field initialization follows a fixed order: default values, explicit initialization, constructor assignments, and finally manual assignments via methods or direct field access.

The this keyword references the current instance. It disambiguates between parameters and instance variables, calls overloaded constructors (must be the first statement), and invokes instance methods:

public class Rectangle {
    private int width;
    private int height;

    public Rectangle() {
        this(10, 20);   // must come first
    }

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public Rectangle(int size) {
        this(size, size);  // square
    }

    public void scale(int factor) {
        this.width *= factor;
        this.height *= factor;
    }
}

Package declarations organize classes into namespaces and appear first in a source file:

package com.example.inventory;

The import statement brings external classes into scope. Its placed after the package declaration and before the class definition. Avoid importing classes with * when name conflicts exist; resolve them with fully qualified names. Use import static to bring in static members directly:

import java.util.ArrayList;
import java.util.Date;
import static java.lang.Math.*;

public class WarehouseManager {
    public static void main(String[] args) {
        ArrayList<String> items = new ArrayList<>();
        double radius = 5.0;
        double area = PI * pow(radius, 2);
    }
}

Tags: java OOP encapsulation Constructors Access Modifiers

Posted on Tue, 16 Jun 2026 16:01:15 +0000 by verdrm