OOP in one minute, classes vs objects, every way to create an object, the Object class methods, packages, access modifiers and why getters/setters beat public fields.
Published September 25, 2026
This chapter's questions test whether you can explain OOP in plain language and back it up with code. Keep definitions short and follow each one with a real example: a BankAccount, an Order, an Employee. It sounds far more convincing than textbook phrasing.
Short answer: OOP organises a program around objects, which bundle data (fields) with the behaviour that operates on it (methods). Java builds on four principles:
public class BankAccount { // class = blueprint
private long balancePaise; // encapsulated state
public void deposit(long amountPaise) { // behaviour guards the state
if (amountPaise <= 0) throw new IllegalArgumentException("amount must be positive");
balancePaise += amountPaise;
}
public long balance() { return balancePaise; }
}
BankAccount acc = new BankAccount(); // object = one instance with its own state
Key points to cover:
Learn it in depth → Classes and Objects
Short answer: A class is a blueprint that defines state (fields) and behaviour (methods). An object is a concrete instance of that class, created at runtime with its own copy of the instance fields.
Key points to cover:
new Employee("Asha") and new Employee("Ravi") share the code but have different state.static members that belong to the class itself, not to any object.Learn it in depth → Classes and Objects
Short answer:
new keyword.Constructor.newInstance().clone().Employee e1 = new Employee("Asha"); // 1. new
Employee e2 = Employee.class.getDeclaredConstructor(String.class)
.newInstance("Ravi"); // 2. reflection
Employee e3 = e1.clone(); // 3. clone (needs Cloneable + an overridden clone())
Employee e4 = (Employee) objectInputStream.readObject(); // 4. deserialization
List<String> names = List.of("a", "b"); // 5. static factory
Key points to cover:
Class.newInstance() is deprecated. Use getDeclaredConstructor().newInstance().clone() and deserialization don't run the constructor, so invariants that constructors enforce can be bypassed. That's a known security and correctness risk.Short answer: Yes. An empty class is legal: class Marker {}. It still inherits everything from Object (toString, equals, hashCode, …), and you can create instances of it.
Key points to cover:
Serializable (empty interfaces rather than classes).class InsufficientFundsException extends RuntimeException {}.Object class provide?Short answer: equals(), hashCode(), toString(), getClass(), clone(), wait(), notify(), notifyAll(), and the deprecated finalize().
Key points to cover:
| Method | Purpose | Override? |
|---|---|---|
equals(Object) | Logical equality (defaults to ==) | Yes, for value-like classes |
hashCode() | Hash for HashMap/HashSet; must agree with equals | Always together with equals |
toString() | Readable text for logs and debugging | Almost always |
getClass() | Runtime class | Can't (it's final) |
clone() | Field-by-field copy (protected, needs Cloneable) | Rarely; prefer copy constructors |
wait/notify/notifyAll | Low-level thread coordination on a monitor | Can't (they're final) |
finalize() | Deprecated cleanup hook | Never |
equals, hashCode and toString for you.Learn it in depth → equals() and hashCode()
Short answer: A package is a namespace that groups related classes and interfaces, such as java.util or com.shop.orders. It maps to a folder structure on disk.
Key points to cover:
package com.shop.orders; as the first statement in a file. Classes in other packages are used through import.com.company.product.module), which keeps names unique worldwide.java.lang is imported automatically) and user-defined ones.Short answer: To organise code, avoid naming conflicts, and control access.
Key points to cover:
…orders.api, …orders.domain, …orders.persistence).java.util.Date and java.sql.Date can both exist.module-info.java) export or hide.Short answer: Four levels, from most to least open: public, protected, default (package-private, meaning no keyword), and private.
| Modifier | Same class | Same package | Subclass (other package) | Everywhere |
|---|---|---|---|---|
public | ✅ | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ✅ (through inheritance) | ❌ |
| default | ✅ | ✅ | ❌ | ❌ |
private | ✅ | ❌ | ❌ | ❌ |
Learn it in depth → Classes and Objects
Short answer: Start with the most restrictive level that works:
private for fields and internal helpers.protected for extension points meant for subclasses.public only for the API that other code is meant to use.Key points to cover:
account.deposit(x) rather than setBalance(). For pure data carriers, use an immutable record.public void setPrice(BigDecimal price) {
if (price.signum() < 0) throw new IllegalArgumentException("price cannot be negative");
this.price = price;
}
Common trap: saying "getters and setters are encapsulation". A public setter for every field exposes the state just as much as a public field does. Encapsulation means protecting invariants.
private or protected?Short answer: No. A top-level class can only be public or package-private. private and protected only make sense relative to an enclosing class, so they're allowed on nested classes.
public class Outer {
private static class Helper { } // fine: nested
protected class Inner { } // fine: nested
}
// private class Top { } // compile error: modifier private not allowed here
Key points to cover:
.java file can have at most one public top-level class, and it must match the file name.Q: Is protected more or less restrictive than default access?
A: Less restrictive. protected includes everything default access allows (same package), and adds subclasses in other packages.
Q: What's the difference between import and a static import?
A: import lets you use a class by its simple name. import static lets you use a class's static members directly, for example import static java.lang.Math.max; and then max(a, b). Use static imports sparingly, because they can hide where a method comes from.
Q: How are Java modules different from packages?
A: A package groups classes. A module (Java 9+) groups packages, and declares which of them it exports and which modules it requires. That gives you strong encapsulation: even public classes in non-exported packages can't be used from outside the module.
Q: Why prefer a copy constructor over clone()?
A: clone() has an awkward contract: the Cloneable marker, a protected method, shallow copies by default, and no constructor call. A copy constructor or a static factory (new Order(other), Order.copyOf(other)) is explicit, type safe, and easy to make a deep copy.