In Java, Object-Oriented Programming (OOP) models software systems around real-world data and behavior:
new keyword. Each object possesses its own isolated state while sharing method bytecode with all other instances.extends)
Encapsulation is the bundling of data (fields) and the methods that operate on that data into a single unit (class), while restricting direct outside access to internal representation.
By making fields private and providing public getter and setter methods, classes enforce business validation invariants (e.g., preventing a bank account balance from becoming negative).
private: Accessible only within the declaring class. Invisible to subclasses and other classes in the same package.protected: Accessible within the same package AND by subclasses in different packages via inheritance.public: Accessible from any class in any package across the entire application.| Access Modifier | Same Class | Same Package Subclass | Same Package Non-Subclass | Different Package Subclass | Different Package Non-Subclass |
|---|---|---|---|---|---|
public |
✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes |
protected |
✓ Yes | ✓ Yes | ✓ Yes | ✓ Yes (Inherited) | ✗ No |
| Default (no modifier) | ✓ Yes | ✓ Yes | ✓ Yes | ✗ No | ✗ No |
private |
✓ Yes | ✗ No | ✗ No | ✗ No | ✗ No |
super Keyword
Inheritance allows a derived subclass to inherit fields and methods from a parent superclass using the extends keyword. Java supports:
Java deliberately does NOT support multiple inheritance of classes (i.e., class C extends A, B is illegal).
If Class A defines a method display(), and both Subclasses B and C override it, and Class D were allowed to inherit from both B and C, calling d.display() creates an irreconcilable ambiguity: should the JVM invoke B's or C's implementation? This is the classic Diamond Problem. Java cleanly solves this by permitting multiple inheritance only through Interfaces!
super Keywordsuper(): Calls the superclass constructor. Must be the very first statement in a subclass constructor.super.methodName(): Invokes an overridden superclass method from within the overriding subclass method.super.fieldName: Accesses a superclass field that is shadowed/hidden by a field of the same name in the subclass.protected, child can be protected or public, but not private).private, static, and final methods cannot be overridden.@Override so the compiler catches accidental signature typos.Employee emp = @0xHeapRef@0xHeapRef [ Manager Object ]emp.calculateBonus() invokedManager ➔ Executes Manager.calculateBonus()!
Abstraction is the principle of hiding internal implementation details and exposing only essential functional interfaces to the consumer:
abstract): A partially implemented template. Can contain abstract methods (no body) as well as concrete methods, instance state variables, and constructors. Cannot be directly instantiated via new. Represents an IS-A identity relationship.interface): A pure behavioral contract. A class can implement multiple interfaces (implements A, B, C), enabling multiple behavioral inheritance. Represents a CAN-DO capability contract.| Dimension | Abstract Class | Interface |
|---|---|---|
| Inheritance Modality | Single inheritance (extends SingleClass) |
Multiple implementation (implements InterfaceA, B) |
| State & Fields | Can have instance variables of any access type | Fields are implicitly public static final (Constants only) |
| Constructors | Has constructors (called via super()) |
Cannot have constructors |
| Method Implementations | Can have both abstract and fully concrete methods | Abstract methods by default; allows default and static methods (Java 8+) |
| Design Purpose | Code reuse among closely related domain classes | Defining standardized peripheral capabilities across unrelated classes |
final Keyword in Java
A package is a namespace mechanism that groups related classes and interfaces into a directory hierarchy. Packages prevent naming collisions (e.g., java.util.Date vs. java.sql.Date) and provide access protection boundaries (package-private). Standard enterprise convention uses inverted internet domain names: package me.devascentacademy.finance;.
final Keywordpublic final class String). Prevents malicious subclasses from breaking immutability guarantees.
This comprehensive application unites all four pillars of OOP:
abstract class templates with super() constructor chaining, interface contracts (Auditable), dynamic method dispatch polymorphism, encapsulated fields with getter validation, and final security tokens.
/**
* DevAscent Academy — Unit 6 Capstone Project
* Demonstrates Encapsulation, Inheritance, Polymorphism, Abstraction, and Interfaces.
*/
// 1. Interface: Behavioral Contract
interface Auditable {
void logAuditTrail(String auditId);
}
// 2. Abstract Superclass: Domain Foundation
abstract class PaymentTransaction implements Auditable {
private final String transactionId; // Encapsulated immutable state
private double amount;
// Superclass Constructor
public PaymentTransaction(String transactionId, double amount) {
this.transactionId = transactionId;
this.setAmount(amount);
}
// Encapsulated Getter & Setter with business validation
public double getAmount() { return this.amount; }
public void setAmount(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Amount must be positive.");
this.amount = amount;
}
public String getTransactionId() { return this.transactionId; }
// Abstract Method: Enforces dynamic polymorphic implementation
public abstract void processPayment();
// Concrete Implementation of Interface Method
@Override
public void logAuditTrail(String auditId) {
System.out.printf(" [AUDIT-%s] Txn %s verified on compliance ledger.%n",
auditId, this.transactionId);
}
}
// 3. Concrete Subclass A: Credit Card Payment
class CreditCardPayment extends PaymentTransaction {
private final String cardLast4;
public CreditCardPayment(String txnId, double amount, String cardLast4) {
super(txnId, amount); // Calling Superclass Constructor
this.cardLast4 = cardLast4;
}
@Override
public void processPayment() {
System.out.printf("Charging Credit Card (**** **** **** %s) | Amount: $%.2f [SUCCESS]%n",
this.cardLast4, this.getAmount());
}
}
// 4. Concrete Subclass B: Crypto Wallet Payment
class CryptoPayment extends PaymentTransaction {
private final String walletAddress;
public CryptoPayment(String txnId, double amount, String walletAddress) {
super(txnId, amount);
this.walletAddress = walletAddress;
}
@Override
public void processPayment() {
System.out.printf("Broadcasting to Blockchain Wallet (%s) | Amount: $%.2f [CONFIRMED]%n",
this.walletAddress, this.getAmount());
}
}
// 5. Execution Controller
public class PaymentArchitectureDemo {
public static void main(String[] args) {
System.out.println("==================================================");
System.out.println(" DEVASCENT ENTERPRISE PAYMENT DISPATCH ENGINE ");
System.out.println("==================================================");
// Polymorphic Array: Superclass reference array holding derived objects
PaymentTransaction[] paymentQueue = {
new CreditCardPayment("TXN-801", 249.99, "4482"),
new CryptoPayment("TXN-802", 1200.00, "0x7A1F...99B"),
new CreditCardPayment("TXN-803", 34.50, "1109")
};
// Dynamic Method Dispatch: JVM resolves correct subclass implementation at runtime!
for (PaymentTransaction txn : paymentQueue) {
System.out.println("Initiating Txn ID: " + txn.getTransactionId());
txn.processPayment(); // Polymorphic dispatch
txn.logAuditTrail("SEC99");
System.out.println("--------------------------------------------------");
}
}
}
InterfaceA.super.method()).
Parent p = new Child(); p.method();), the JVM inspects the object's internal Virtual Method Table (vtable) located in heap metadata to find the memory address of the overriding subclass method, executing it dynamically.
new AbstractClass(), its constructors are executed during subclass instantiation when the subclass constructor calls super(). This ensures that the abstract superclass's state fields and initialization invariants are properly configured.
String class declared final in Java?String were not final, an unauthorized developer could create a subclass (e.g., MutableString) that overrides methods like hashCode() or allows mutation of internal character arrays. Because Strings are fundamental to JVM security (holding database credentials, socket configurations, and classloading paths), declaring String final guarantees that its immutability contract can never be broken or spoofed.
protected, the subclass method can be protected or public, but cannot be default (package-private) or private. This adheres to the Liskov Substitution Principle: a subclass must fulfill at least the visibility contract of its parent.
SuperClass.produce() returns Animal, the overriding SubClass.produce() is legally allowed to return Dog without requiring type casting by the caller.
default keyword) allow interfaces to provide concrete method implementations. They were introduced to ensure backward compatibility: allowing architects to add new methods to existing foundational interfaces (such as adding stream() and forEach() to java.util.Collection) without breaking millions of legacy third-party classes that implemented those interfaces.