Classes & Objects

Course 1 · Ch 4
Classes & Objects
A fourth access level neither C++ nor Rust really has — and why it exists

Every program since java1-1 has lived inside a class out of necessity. This chapter explains why — fields, constructors, methods, and the access-control model that governs who can touch what.

Fields & Constructors

public class Account { private String owner; // a field — instance state private double balance; public Account(String owner, double balance) { // a constructor — no return type, matches the class name this.owner = owner; // this disambiguates the field from the parameter this.balance = balance; } public double getBalance() { return balance; } }

A constructor shares the class's exact name, has no return type, and runs once when new Account(...) is called. this refers to the current instance — needed here specifically because the parameter names shadow the field names.

Java's Four Access Levels

Where C++ has three access levels (public, protected, private), Java has a genuine fourth: package-private, the default when no modifier is written at all. A member with no modifier is visible to any class in the same package, but nowhere else — a level of granularity C++ has no direct equivalent for.

ModifierVisible fromC++ equivalent
publicanywherepublic
protectedsame package + subclasses anywhereprotected (subclasses only, no package concept)
(none) — package-privatesame package onlyno direct equivalent
privatesame class onlyprivate

Why a Fourth Level Exists

C++ has no built-in concept of a "package" the way Java does, so it has nothing to attach a package-scoped access level to in the first place. Java's package system gives classes in the same package a middle ground: more open than private, but without exposing a member to every caller everywhere the way public does. It's a genuinely different granularity, not just a naming difference.

Instance Methods vs. Static Methods

public double getBalance() { return balance; } // instance method — needs an object public static Account empty() { // static method — no object needed at all return new Account("none", 0.0); }

main, back in java1-1, was already static — this is why: a static method belongs to the class itself, not to any particular instance, which is exactly why the JVM can call main without ever constructing an object first.

Default to private, widen only when needed
Start every field private and every method as narrowly scoped as the design allows — widen to package-private, then protected, then public only when a real caller outside that scope genuinely needs access.
Forgetting the modifier is not "public by default"
Omitting an access modifier does not mean "public" the way it's easy to assume coming from a language without this exact default — it means package-private, a real, distinct, narrower level of its own.

Coding Challenges

Challenge 1

Write a class Rectangle with private width and height fields, a constructor that sets both using this, and a public method area() that returns their product.

📄 View solution
Challenge 2

Write a class with one package-private field (no modifier) and explain in a comment exactly which callers can and cannot access it, contrasting it with what private and public would each allow.

📄 View solution
Challenge 3

Write a static factory method inside a class called origin() that returns a new instance representing coordinates (0, 0), and explain why it must be static in order to be called before any instance exists.

📄 View solution

Chapter 4 Quick Reference

  • A constructor shares the class name exactly, has no return type, and runs once per new instance
  • this disambiguates a field from a same-named parameter inside a constructor or method
  • Java has four access levels: public, protected, package-private (the default, no modifier), and private — a genuine fourth level C++'s three don't have
  • Package-private exists because Java has a real package concept C++ doesn't — a middle ground between private and public
  • static methods belong to the class itself, not an instance — exactly why main can run with no object constructed first
  • Next chapter: inheritance, polymorphism, and Java's single-inheritance-of-classes model