Day 18 / 25 Java Classes, Objects & Encapsulation 0/0 exercises Exercises ↓

AmouAI Hub/Courses/Programming Fundamentals/Day 18

Week 4 · Java: A Second Lens · Day 18

Java Classes, Objects & Encapsulation

Constructors, access modifiers, and why Java needs getters and setters where Python reaches for @property.

Study time
4 hours
Reading
Head First Java, Ch. 5–6, 9
Focus
constructors · access · toString

By the end of today you can

  1. Write a Java class with fields, a constructor and methods
  2. Overload a constructor, and chain with this(...)
  3. Choose between public, private and protected deliberately
  4. Say why Java's private is enforced and Python's _name is not
  5. Write getters and setters, and say what they buy
  6. Override toString, equals and hashCode — and why the last two travel together
  7. Translate a Python class into Java without losing its invariants

Today's videos

Watch each video, then work the matching sections below. Watching alone will not do it.

18A
Classes, Fields & Constructors (120 min)
Declaring fields with types · this versus self · constructor overloading and chaining with this(...) · final · the integer division bug that Java's type system does not save you from.
18B
Access, toString, equals & hashCode (120 min)
public/private/protected enforced by a compiler · getters and setters, and why @property made them unnecessary in Python · the equals/hashCode contract and the silent bug when you break it · records.

1The same class, in both languages

Start with Day 12's Book and see what Java demands.

The integer division trap

read / pages where both are int gives an int100 / 292 is 0, and progress() cheerfully returns 0.0. No error, no warning. This is a semantic error in exactly the sense Day 5 defined, and Java's type system does not save you from it. Cast one side to double.

final

private final String title says the field can never be reassigned after construction. Python has no equivalent — the closest is a @property with no setter. Marking fields final wherever possible removes a whole category of "who changed this?" questions.

2Constructors

Overloaded, and chained.

Book.java
public class Book {
    private final String title;
    private final int pages;
    private int read;

    // full constructor
    public Book(String title, int pages, int read) {
        if (pages <= 0) {
            throw new IllegalArgumentException("pages must be positive: " + pages);
        }
        this.title = title;
        this.pages = pages;
        this.read = read;
    }

    // convenience constructor — delegates, never duplicates
    public Book(String title, int pages) {
        this(title, pages, 0);
    }
}
this(...) must be the first statement

Chaining to another constructor is how you avoid copying the validation into every overload. Java enforces that the chained call comes first, so the object is never half-built. Python's equivalent is a default argument — one constructor, read=0 — which is simpler, and is why Python needs no chaining rule.

3Access modifiers

Where Python asks nicely, Java refuses.

ModifierVisible toPython's nearest thing
publicEverythinga plain name
protectedThis class, subclasses, same package_name, loosely
(none)Same package onlyno equivalent
privateThis class only__name, and even that is only mangled

Which is why Java needs getters

Getters.java
public class Book {
    private int read = 0;
    private final int pages;

    public int getRead() {
        return read;
    }

    public void setRead(int value) {
        if (value < 0 || value > pages) {
            throw new IllegalArgumentException("read out of range: " + value);
        }
        this.read = value;
    }
}
Now Day 13's @property makes sense

Java writes getRead()/setRead() from the start, because turning a public field into a method later would break every caller. Python does not need to: @property lets book.read keep working while validation appears behind it. Same goal — controlled access — reached from opposite directions. Which is better? Java's is more ceremony and more guarantee. Python's is less ceremony and relies on the team. You have now written both, so the opinion is yours.

4toString, equals and hashCode

Three methods every value class should override — and two of them are a pair.

Contact.java
import java.util.Objects;

public class Contact {
    private final String name;
    private final String email;

    public Contact(String name, String email) {
        this.name = name;
        this.email = email;
    }

    @Override
    public String toString() {
        return "Contact(" + name + ", " + email + ")";
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) return true;
        if (!(other instanceof Contact)) return false;
        Contact c = (Contact) other;
        return name.equals(c.name) && email.equals(c.email);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, email);
    }
}
Override equals without hashCode and you get a silent bug

The contract is: equal objects must have equal hash codes. Break it and your objects behave correctly with .equals() but wrongly in a HashMap or HashSet — you put a contact in, ask whether an equal one is present, and get false. This is Day 9's hashing lesson: the hash decides the bucket, and if two equal objects hash differently they land in different buckets and never meet.

Records make most of this vanish

Since Java 16: public record Contact(String name, String email) {} generates the constructor, getters, toString, equals and hashCode for you — the whole file above in one line. Write it by hand once so you know what is being generated, then use records. Python's equivalent is @dataclass.

>_Python playground

A real Python interpreter running inside your browser. Nothing is installed, nothing is uploaded, nothing can break.

scratch.pypython not loaded
Values for input(), comma separated →
Output appears here. The first run takes a few seconds while Python loads.

Exercise set

Checked automatically the moment you submit. Work top to bottom — each one assumes the last. Your answers are saved in this browser.

All Warm-up Core Challenge Reset day

Day 19 — Java Inheritance, Interfaces & Polymorphism

Interfaces are the idea Python never forces you to learn.

Continue →