16. జావా ఎన్‌క్యాప్సులేషన్, Access Modifiers & రికార్డ్స్ (Encapsulation & Records)

☕ Java (Java 21+ LTS) 🟢 Lesson 16 of 25 📂 Part 04: Core OOP & Exceptions (Page 1 of 5) ⏱️ 26 min read
📌 Covered in this lesson: డేటా హైడింగ్ సూత్రం · Access Modifiers (private, default, protected, public) · Getters & Setters Validation · Modern Java records (ఇమ్మ్యుటబుల్ డేటా క్యారియర్స్)

ఆబ్జెక్ట్-ఓరియెంటెడ్ ప్రోగ్రామింగ్ (OOP) యొక్క మొట్టమొదటి మరియు అత్యంత ముఖ్యమైన రక్షణ కవచం ఎన్‌క్యాప్సులేషన్ (Encapsulation). ఒక సాఫ్ట్‌వేర్ సిస్టమ్‌లో డేటా అనేది అత్యంత విలువైన ఆస్తి; దానిని ఎవరైనా ఇష్టానుసారంగా మార్చకుండా కాపాడటమే (Data Hiding) ఎన్‌క్యాప్సులేషన్ యొక్క అంతిమ లక్ష్యం. జావాలో డేటాను ఒక బౌండరీ లోపల బంధించి, కఠినమైన నిబంధనలతో కూడిన సురక్షిత ద్వారాలు (Public Getters/Setters) ద్వారా మాత్రమే బాహ్య ప్రపంచానికి అనుమతిస్తాం. జావాలోని 4 యాక్సెస్ మోడిఫైయర్లు (private, default, protected, public) ప్యాకేజీల పరిధిలో ఎలా పనిచేస్తాయి? రిఫరెన్స్ లీక్‌లను అరికట్టే డిఫెన్సివ్ కాపీయింగ్ (Defensive Copying) ప్రాముఖ్యత ఏమిటి? మరియు ఆధునిక జావా 14+ లో సాంప్రదాయ బాయిలర్‌ప్లేట్ కోడ్‌ను సమూలంగా తుడిచిపెట్టేసిన సరికొత్త Java Records (record) ఎలా పనిచేస్తాయి? అనే సంపూర్ణ ఆర్కిటెక్చరల్ వివరాలను ఈ పాఠంలో లోతుగా నేర్చుకుందాం.

మెడిసిన్ క్యాప్సూల్ & బ్యాంక్ సేఫ్టీ లాకర్ల అనాలజీ (The Medicine Capsule & Bank Safety Locker Analogy):

  1. 1. Encapsulation (మెడిసిన్ క్యాప్సూల్ - Medical Capsule Analogy): అనారోగ్యంతో ఉన్నప్పుడు మనం వేసుకునే క్యాప్సూల్ లోపల అనేక రకాల కెమికల్ పౌడర్లు (Fields / Data) సురక్షితంగా మూసి ఉంటాయి. బాహ్య వాతావరణంలోని తేమ లేదా చేతి దుమ్ము నేరుగా ఆ కెమికల్స్‌ను తాకలేదు. బయట ఉండే జిలాటిన్ పొర (Public Methods) కడుపులోకి వెళ్లాక కరిగి, రక్తంలోకి ఔషధాన్ని నియంత్రిత రీతిలో విడుదల చేస్తుంది. ఇదే ఎన్‌క్యాప్సులేషన్ — డేటాను దాచి, సురక్షితమైన పబ్లిక్ మెథడ్స్ ద్వారా మాత్రమే యాక్సెస్ కల్పించడం!
  2. 2. Access Modifiers (బ్యాంక్ 4-టైర్ సెక్యూరిటీ జోన్లు - 4-Tier Security Zones):
    • private (అండర్‌గ్రౌండ్ స్ట్రాంగ్ రూమ్): కేవలం ఆ నిర్దిష్ట బ్రాంచ్ స్ట్రాంగ్ రూమ్ ఆఫీసర్‌కు మాత్రమే ప్రవేశం (కేవలం అదే క్లాస్ లోపల).
    • default (సిబ్బంది వర్క్‌స్టేషన్): ఆ బ్యాంక్ బ్రాంచ్‌లోని సిబ్బంది అందరికీ ప్రవేశం (కేవలం అదే Package లోపల).
    • protected (ఫ్యామిలీ లాకర్ రూమ్): బ్యాంక్ భాగస్వాములు మరియు వారి అధీకృత వారసులకు (Subclasses in any package) మాత్రమే అనుమతి.
    • public (ఏటీఎం కౌంటర్ లేదా హెల్ప్ డెస్క్): రోడ్డుపై వెళ్లే ఎవరైనా సరే ఉపయోగించుకోవచ్చు (మొత్తం వరల్డ్/అన్ని ప్యాకేజీలు).
  3. 3. Java Records (ముద్రించిన ప్రభుత్వ ఆధార్ కార్డు - Immutable Record Card): ఒకసారి అధికారికంగా ఆధార్ కార్డు ప్రింట్ అయిన తర్వాత, ఎవరూ పెన్నుతో దానిపై పేరును లేదా పుట్టిన తేదీని మార్చలేరు (Immutable). కేవలం చదవడానికి (Read-Only) మాత్రమే వీలవుతుంది. ఆధునిక జావా 14+ రికార్డ్స్ అనేవి వందల లైన్ల Getters, equals(), hashCode(), toString() బాయిలర్‌ప్లేట్ కోడ్ లేకుండా కేవలం ఒక్క లైన్‌లోనే ఇమ్మ్యుటబుల్ డేటా క్యారియర్లను నిర్మించే అద్భుతమైన వరం!

ఈ పాఠం పూర్తయ్యేసరికి మీరు భద్రమైన బిజినెస్ మోడల్స్ నిర్మించడం, డిఫెన్సివ్ ప్రోగ్రామింగ్ ద్వారా డేటా కరప్షన్‌ను అరికట్టడం, మరియు ఆధునిక రికార్డ్స్‌తో ఎంటర్‌ప్రైజ్ హెల్త్‌కేర్ మెడికల్ రికార్డ్ ఇంజిన్‌ను తయారు చేయడంలో సంపూర్ణ నిపుణులవుతారు!

📑 ఈ పాఠంలో మీరు నేర్చుకునే అంశాలు (Table of Contents)
విభాగం A: ఎన్‌క్యాప్సులేషన్ & యాక్సెస్ లెవల్స్
విభాగం B: డిఫెన్సివ్ కాపీయింగ్ & Records
విభాగం C: డెమోలు, ప్రాజెక్ట్ & పరీక్ష

1. ఎన్‌క్యాప్సులేషన్ అంటే ఏమిటి? డేటా హైడింగ్ ఆవశ్యకత (Encapsulation & Data Hiding)

ఒక క్లాస్ లోని వేరియబుల్స్ (Data Fields) మరియు ఆ వేరియబుల్స్‌పై పనిచేసే మెథడ్స్ (Methods) రెండింటినీ ఒకే యూనిట్‌గా బంధించి, డేటాను బయటి క్లాసులు నేరుగా యాక్సెస్ చేయకుండా నిరోధించే ప్రక్రియనే ఎన్‌క్యాప్సులేషన్ (Encapsulation) అంటారు.

జావాలో ఎన్‌క్యాప్సులేషన్‌ను సాధించడానికి రెండు సూత్రాలను తప్పనిసరిగా పాటిస్తాం:
1. క్లాస్ లోని ఫీల్డ్స్ అన్నింటినీ private గా ప్రకటించడం (Data Hiding).
2. ఆ ఫీల్డ్స్ యొక్క విలువలను చదవడానికి మరియు మార్చడానికి పబ్లిక్ Getters & Setters మెథడ్లను అందించడం.

💡 ఎందుకు ముఖ్యం? ఫీల్డ్స్ పబ్లిక్‌గా ఉంటే, ఏ బయటి డెవలపర్ అయినా account.balance = -999999; అని రాయగలడు. కానీ సెట్టర్ మెథడ్ ద్వారా నియంత్రించినప్పుడు (account.setBalance(amount)), మనం లోపల వ్యాపార నిబంధనలను (Business Rules) తనిఖీ చేసి తప్పుడు విలువలను తిరస్కరించవచ్చు!

2. 4 Access Modifiers లోతైన విశ్లేషణ (The 4 Access Modifiers)

జావాలో ఒక క్లాస్, వేరియబుల్, మెథడ్ లేదా కన్‌స్ట్రక్టర్ ఎవరెవరికి అందుబాటులో ఉండాలో నిర్దేశించే నాలుగు యాక్సెస్ లెవల్స్ ఉన్నాయి:

  • 1. private (అత్యంత కఠినమైనది): కేవలం ఆ నిర్దిష్ట క్లాస్ బౌండరీ (Curly braces { }) లోపల మాత్రమే కనిపిస్తుంది. బయటి ఏ క్లాస్, ఏ ప్యాకేజీ కూడా దీన్ని నేరుగా తాకలేదు.
  • 2. Package-Private / Default (ఎటువంటి మోడిఫైయర్ లేకపోతే): ఒక వేరియబుల్ లేదా మెథడ్ ముందు ఏ మోడిఫైయర్ రాయకపోతే, అది 'డీఫాల్ట్' అవుతుంది. ఇది కేవలం అదే ప్యాకేజీ (Same Package) లోని ఇతర క్లాసులకు మాత్రమే అందుబాటులో ఉంటుంది.
  • 3. protected (వారసత్వానికి రక్షణ): అదే ప్యాకేజీ లోని అన్ని క్లాసులకు మరియు ఇతర ప్యాకేజీలలో ఉన్నప్పటికీ ఈ క్లాస్‌ను ఎక్స్‌టెండ్ చేసుకున్న చైల్డ్ సబ్‌క్లాసులకు (Subclasses in any package) మాత్రమే అందుబాటులో ఉంటుంది.
  • 4. public (సార్వత్రిక ప్రవేశం): మొత్తం ప్రాజెక్ట్‌లోని ఏ ప్యాకేజీ, ఏ క్లాస్ నుండి అయినా నేరుగా యాక్సెస్ చేయవచ్చు.

3. Package Architecture & విజిబిలిటీ మ్యాట్రిక్స్ (The Definitive Visibility Table)

జావా ఇంటర్వ్యూలలో అత్యంత ప్రాచుర్యం పొందిన ప్రశ్నలలో ఒకటైన యాక్సెస్ లెవల్స్ టేబుల్‌ను క్రింద స్పష్టంగా పరిశీలిద్దాం:

లొకేషన్ / స్కోప్ private default (no keyword) protected public
అదే క్లాస్ (Same Class) ✅ అవును ✅ అవును ✅ అవును ✅ అవును
అదే ప్యాకేజీ (Same Package) ❌ కాదు ✅ అవును ✅ అవును ✅ అవును
భిన్న ప్యాకేజీ సబ్‌క్లాస్ (Different Package Subclass) ❌ కాదు ❌ కాదు ✅ అవును ✅ అవును
భిన్న ప్యాకేజీ నాన్-సబ్‌క్లాస్ (World Outside) ❌ కాదు ❌ కాదు ❌ కాదు ✅ అవును

4. Getters, Setters & బిజినెస్ రూల్స్ వాలిడేషన్ (Validation Gates)

చాలామంది బిగినర్లు IDE ఇచ్చిన షార్ట్‌కట్ వాడి అన్ని ఫీల్డ్స్‌కూ గుడ్డిగా Getters మరియు Setters జనరేట్ చేస్తారు. కానీ వాస్తవ ఎంటర్‌ప్రైజ్ కోడ్‌లో సెట్టర్ అనేది ఒక సెక్యూరిటీ చెక్‌పోస్ట్ లాంటిది:

public void setAge(int age) {
    if (age < 0 || age > 125) {
        throw new IllegalArgumentException("చెల్లని వయస్సు: " + age);
    }
    this.age = age;
}

ఒక ఫీల్డ్ మారకూడదనుకుంటే (Read-Only Field), దానికి కేవలం Getter మాత్రమే ఇచ్చి, Setter ను అసలు రాయకపోవడం ద్వారా పూర్తి ఇమ్మ్యుటబిలిటీని సాధించవచ్చు!

5. డిఫెన్సివ్ కాపీయింగ్ (Defensive Copying) ఎందుకు తప్పనిసరి? (The Reference Leak Trap)

ఒక క్లాస్‌లోని అన్ని ఫీల్డ్‌లను private final గా పెట్టినా కూడా ఎన్‌క్యాప్సులేషన్ విఫలమయ్యే తీవ్రమైన సెక్యూరిటీ ప్రమాదం ఉంది. అది మ్యూటబుల్ ఆబ్జెక్ట్ రిఫరెన్స్ లీక్ అయినప్పుడు జరుగుతుంది!

⚠️ రిఫరెన్స్ లీక్ ప్రమాదం (Unsafe Getter):
public class PatientHistory {
    private final Date admissionDate; // Date అనేది మ్యూటబుల్ ఆబ్జెక్ట్!
    public Date getAdmissionDate() {
        return this.admissionDate; // ❌ ప్రమాదం! అసలు రిఫరెన్స్ బయటకు వెళ్ళిపోయింది!
    }
}
// బయట కాలర్ నేరుగా మార్చేయవచ్చు:
history.getAdmissionDate().setYear(1990); // ❌ క్లాస్ స్టేట్ కరప్ట్ అయింది!

డిఫెన్సివ్ కాపీయింగ్ పరిష్కారం: Getter లో అసలు ఆబ్జెక్ట్‌ను ఇవ్వకుండా, దాని యొక్క సరికొత్త క్లోన్ లేదా కాపీని మాత్రమే బయటకు పంపాలి (return new Date(this.admissionDate.getTime());). లేదా ఆధునిక జావాలో పాత Date కు బదులుగా ఇమ్మ్యుటబుల్ అయిన java.time.LocalDate ను వాడాలి!

6. Java 14+ Records (record కీవర్డ్) విప్లవం (Modern Immutable Carriers)

సాంప్రదాయ జావాలో కేవలం డేటాను మోసే సాధారణ క్లాస్ (DTO - Data Transfer Object) రాయాలంటే కనీసం 50 నుండి 80 లైన్ల బోరింగ్ కోడ్ రాయాల్సి వచ్చేది: private final ఫీల్డ్స్, కన్‌స్ట్రక్టర్, ప్రతి ఫీల్డ్‌కు Getter, equals(), hashCode(), మరియు toString().

Java 14 (JEP 359/395) నుండి వచ్చిన Records ఈ సమస్యను కేవలం ఒకే ఒక్క లైన్‌తో పరిష్కరించాయి!

// కేవలం ఒక్క లైన్ జావా రికార్డ్:
public record UserProfile(Long id, String username, String email) {}

పై ఒక్క లైన్ కోసం జావా కంపైలర్ తెరవెనుక స్వయంగా ఇవన్నీ చేస్తుంది:
• అన్ని కాంపోనెంట్లను private final ఫీల్డ్స్‌గా చేస్తుంది (100% Immutable).
• అన్ని ఫీల్డ్స్‌తో కూడిన కానానికల్ కన్‌స్ట్రక్టర్ (Canonical Constructor) ను ఇస్తుంది.
• ప్రతి ఫీల్డ్‌కు రీడర్ మెథడ్స్ ఇస్తుంది (గమనించండి: getUsername() కాదు, డైరెక్ట్‌గా username() అని పిలుస్తాం!).
• అన్ని ఫీల్డ్‌ల ఆధారంగా equals(), hashCode(), మరియు అందమైన toString() లను స్వయంగా రూపొందిస్తుంది!

7. Compact & Canonical Constructors in Records (Data Validation in Records)

రికార్డ్స్ లో డేటా ఇమ్మ్యుటబుల్ అయినప్పటికీ, ఇన్‌పుట్ విలువలను వాలిడేట్ చేయడానికి జావా కాంపాక్ట్ కన్‌స్ట్రక్టర్ (Compact Constructor) అనే అద్భుతమైన ఫీచర్‌ను అందించింది. ఇందులో పారామీటర్ల బ్రాకెట్లు () ఉండవు, మరియు this.x = x అని రాయాల్సిన పనే లేదు!

public record BankTransfer(String sender, String receiver, double amount) {
    // కాంపాక్ట్ కన్‌స్ట్రక్టర్:
    public BankTransfer {
        if (amount <= 0) {
            throw new IllegalArgumentException("బదిలీ మొత్తం 0 కంటే ఎక్కువ ఉండాలి!");
        }
        // చెల్లుబాటు ముగిసిన వెంటనే కంపైలర్ స్వయంగా ఫీల్డ్స్‌ను అసైన్ చేసుకుంటుంది!
    }
}

8. Traditional Class vs Record సమగ్ర పోలిక (When to Use What)

ప్రొడక్షన్ అప్లికేషన్లలో క్లాస్ ఎప్పుడు వాడాలి, రికార్డ్ ఎప్పుడు వాడాలి అనే స్పష్టత క్రింది పోలిక ద్వారా లభిస్తుంది:

ఫీచర్ / లక్షణం సాధారణ క్లాస్ (Traditional Class) Java Record (record)
మ్యూటబిలిటీ (Mutability) మ్యూటబుల్ లేదా ఇమ్మ్యుటబుల్ గా చేసుకోవచ్చు ఎల్లప్పుడూ 100% ఇమ్మ్యుటబుల్ (Final Fields)
వారసత్వం (Inheritance) వేరే క్లాస్‌ను ఎక్స్‌టెండ్ చేయవచ్చు వేరే క్లాస్‌ను ఎక్స్‌టెండ్ చేయలేదు (Implicitly Final)
ఇంటర్‌ఫేస్ ఇంప్లిమెంటేషన్ ఇంటర్‌ఫేస్‌లను ఇంప్లిమెంట్ చేయవచ్చు ఇంటర్‌ఫేస్‌లను ఇంప్లిమెంట్ చేయవచ్చు
ప్రధాన ఉపయోగం సంక్లిష్ట వ్యాపార లాజిక్, స్టేట్ మార్పులు ఉండే మోడల్స్ DTOs, API Payloads, DB Query Results, Cache Keys

9. డెమో 1: Encapsulation Violation vs Strict Protection (Security Benchmark)

పబ్లిక్ ఫీల్డ్స్ వాడినప్పుడు సిస్టమ్ డేటా ఎలా కరప్ట్ అవుతుందో, మరియు స్ట్రిక్ట్ ఎన్‌క్యాప్సులేషన్ సిస్టమ్‌ను ఎలా కాపాడుతుందో చూపే డెమో:

EncapsulationValidationDemo.java
public class EncapsulationValidationDemo {

    // 1. INSECURE CLASS: Public fields violate encapsulation
    public static class InsecureAccount {
        public String holder;
        public double balance; // Anyone can corrupt this directly!
    }

    // 2. SECURE CLASS: Strictly encapsulated with validation gates
    public static class SecureAccount {
        private String holder;
        private double balance;

        public SecureAccount(String holder, double initialDeposit) {
            this.setHolder(holder);
            this.setBalance(initialDeposit);
        }

        public String getHolder() {
            return holder;
        }

        public void setHolder(String holder) {
            if (holder == null || holder.trim().isEmpty()) {
                throw new IllegalArgumentException("Account holder name cannot be empty!");
            }
            this.holder = holder.trim();
        }

        public double getBalance() {
            return balance;
        }

        public void setBalance(double balance) {
            if (balance < 0.0) {
                System.out.printf("🚨 BLOCKED: Attempt to set negative balance (₹%.2f) rejected!%n", balance);
                return;
            }
            this.balance = balance;
        }
    }

    public static void main(String[] args) {
        System.out.println("=================================================");
        System.out.println("🛡️ ENCAPSULATION VIOLATION VS STRICT VALIDATION");
        System.out.println("=================================================
");

        // Vulnerability Demonstration
        InsecureAccount leaky = new InsecureAccount();
        leaky.holder = "Hacker Target";
        leaky.balance = -50000.0; // ❌ Invalid negative money entered directly!
        System.out.println("1. INSECURE ACCOUNT (No Protection):");
        System.out.println("   Holder: " + leaky.holder + " | Balance: ₹" + leaky.balance + " (CORRUPTED STATE!)");

        // Secure Encapsulated Demonstration
        System.out.println("
2. SECURE ENCAPSULATED ACCOUNT (Validation Gates):");
        SecureAccount safe = new SecureAccount("Balaji Nemani", 5000.0);
        System.out.println("   Initial Balance: ₹" + safe.getBalance());

        // Attempting to set illegal negative balance via setter
        System.out.println("   Attempting safe.setBalance(-25000.0)...");
        safe.setBalance(-25000.0);
        System.out.println("   Final Balance:   ₹" + safe.getBalance() + " (STILL SAFE & UNTOUCHED!)");

        System.out.println("
=================================================");
        System.out.println("✅ Encapsulation successfully prevented data corruption!");
        System.out.println("=================================================");
    }
}
Terminal Output:
=================================================
🛡️ ENCAPSULATION VIOLATION VS STRICT VALIDATION
=================================================

1. INSECURE ACCOUNT (No Protection):
   Holder: Hacker Target | Balance: ₹-50000.0 (CORRUPTED STATE!)

2. SECURE ENCAPSULATED ACCOUNT (Validation Gates):
   Initial Balance: ₹5000.0
   Attempting safe.setBalance(-25000.0)...
🚨 BLOCKED: Attempt to set negative balance (₹-25000.00) rejected!
   Final Balance:   ₹5000.0 (STILL SAFE & UNTOUCHED!)

=================================================
✅ Encapsulation successfully prevented data corruption!
=================================================

10. డెమో 2: Java Records కాంపాక్ట్ కన్‌స్ట్రక్టర్ డెమో (Modern Records Demo)

ఆధునిక జావా రికార్డ్స్ యొక్క స్వయంచాలక ఫీచర్లు, కాంపాక్ట్ కన్‌స్ట్రక్టర్ ద్వారా డేటా వ్యాలిడేషన్ మరియు ఆటో-జెనరేటెడ్ మెథడ్స్ ఎలా పనిచేస్తాయో పరిశీలిద్దాం:

ModernJavaRecordsDeepDiveDemo.java
public class ModernJavaRecordsDeepDiveDemo {

    // Modern Immutable Record with Compact Constructor
    public record DigitalProduct(String sku, String title, double price, int stockQuantity) {

        // Compact Constructor: No parameter list, auto-assigned after validation
        public DigitalProduct {
            if (sku == null || !sku.startsWith("DIG-")) {
                throw new IllegalArgumentException("SKU must start with 'DIG-': " + sku);
            }
            if (price < 0.0) {
                throw new IllegalArgumentException("Price cannot be negative: " + price);
            }
            title = title.trim(); // Clean input before implicit assignment
        }

        // Custom business method inside record
        public boolean isAvailable() {
            return stockQuantity > 0;
        }
    }

    public static void main(String[] args) {
        System.out.println("=================================================");
        System.out.println("⚡ MODERN JAVA 14+ RECORD DEEP DIVE DEMO");
        System.out.println("=================================================
");

        DigitalProduct ebook = new DigitalProduct("DIG-JAVA21", "Modern Java Masterclass", 499.00, 25);

        // 1. Automatic toString()
        System.out.println("1. Built-in toString():");
        System.out.println("   " + ebook);

        // 2. Direct component accessor methods (not getTitle(), just title())
        System.out.println("
2. Component Accessors:");
        System.out.println("   SKU:       " + ebook.sku());
        System.out.println("   Title:     " + ebook.title());
        System.out.println("   Price:     ₹" + ebook.price());
        System.out.println("   In Stock:  " + ebook.isAvailable());

        // 3. Built-in Value Equality (equals & hashCode)
        DigitalProduct identicalEbook = new DigitalProduct("DIG-JAVA21", "Modern Java Masterclass", 499.00, 25);
        System.out.println("
3. Equality Check (Value-based, not reference):");
        System.out.println("   ebook.equals(identicalEbook) ? " + ebook.equals(identicalEbook));
        System.out.println("   HashCode match: " + (ebook.hashCode() == identicalEbook.hashCode()));

        System.out.println("
=================================================");
        System.out.println("✅ Record handled all boilerplate with zero manual code!");
        System.out.println("=================================================");
    }
}
Terminal Output:
=================================================
⚡ MODERN JAVA 14+ RECORD DEEP DIVE DEMO
=================================================

1. Built-in toString():
   DigitalProduct[sku=DIG-JAVA21, title=Modern Java Masterclass, price=499.0, stockQuantity=25]

2. Component Accessors:
   SKU:       DIG-JAVA21
   Title:     Modern Java Masterclass
   Price:     ₹499.0
   In Stock:  true

3. Equality Check (Value-based, not reference):
   ebook.equals(identicalEbook) ? true
   HashCode match: true

=================================================
✅ Record handled all boilerplate with zero manual code!
=================================================

11. Capstone ప్రాజెక్ట్: పేషెంట్ హెల్త్‌కేర్ మెడికల్ రికార్డ్ ఇంజిన్

ఈ అధ్యాయంలో నేర్చుకున్న అన్ని కాన్సెప్టులను (కఠినమైన ఎన్‌క్యాప్సులేషన్, ప్రైవేట్ ఫీల్డ్స్, డిఫెన్సివ్ కాపీయింగ్, వాలిడేషన్ గేట్స్ మరియు Java 14+ Records) సమగ్రంగా మిళితం చేస్తూ ఒక హాస్పిటల్ Healthcare Electronic Medical Record (EMR) & Prescription Audit Engine ను నిర్మిద్దాం:

HealthcarePatientRecordEngine.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class HealthcarePatientRecordEngine {

    // Modern Immutable Prescription Record
    public record MedicationPrescription(String drugName, String dosage, int durationDays) {
        public MedicationPrescription {
            if (drugName == null || drugName.isBlank()) throw new IllegalArgumentException("Drug name required");
            if (durationDays <= 0) throw new IllegalArgumentException("Duration must be at least 1 day");
        }
    }

    // Strictly Encapsulated Patient Medical File
    public static class PatientMedicalFile {
        private final String patientId;
        private String patientName;
        private int age;
        private double weightKg;
        // Mutable list protected via Defensive Copying
        private final List<MedicationPrescription> prescriptions;

        public PatientMedicalFile(String id, String name, int age, double weightKg) {
            if (id == null || !id.startsWith("PAT-")) {
                throw new IllegalArgumentException("Invalid Patient ID format (must start with PAT-): " + id);
            }
            this.patientId = id;
            this.setPatientName(name);
            this.setAge(age);
            this.setWeightKg(weightKg);
            this.prescriptions = new ArrayList<>();
        }

        public String getPatientId() {
            return patientId;
        }

        public String getPatientName() {
            return patientName;
        }

        public void setPatientName(String patientName) {
            if (patientName == null || patientName.trim().isEmpty()) {
                throw new IllegalArgumentException("Name cannot be blank");
            }
            this.patientName = patientName.trim();
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            if (age < 0 || age > 120) throw new IllegalArgumentException("Invalid age boundary");
            this.age = age;
        }

        public double getWeightKg() {
            return weightKg;
        }

        public void setWeightKg(double weightKg) {
            if (weightKg <= 0.0) throw new IllegalArgumentException("Weight must be positive");
            this.weightKg = weightKg;
        }

        public void addPrescription(MedicationPrescription rx) {
            if (rx != null) {
                this.prescriptions.add(rx);
            }
        }

        // Defensive Copying: Returning an unmodifiable view to prevent external list tampering
        public List<MedicationPrescription> getPrescriptions() {
            return Collections.unmodifiableList(this.prescriptions);
        }

        public void printMedicalAudit() {
            System.out.println("-------------------------------------------------");
            System.out.println("🏥 APOLLO HEALTHCARE ELECTRONIC PATIENT DOSSIER");
            System.out.printf("Patient ID:   %s%n", patientId);
            System.out.printf("Full Name:    %s | Age: %d yrs | Weight: %.1f kg%n", patientName, age, weightKg);
            System.out.println("Active Prescriptions (" + prescriptions.size() + "):");
            for (MedicationPrescription rx : prescriptions) {
                System.out.printf("  💊 %-16s | Dosage: %-10s | Course: %d days%n",
                        rx.drugName(), rx.dosage(), rx.durationDays());
            }
            System.out.println("-------------------------------------------------");
        }
    }

    public static void main(String[] args) {
        System.out.println("=================================================");
        System.out.println("🩺 ENTERPRISE HEALTHCARE EMR & AUDIT ENGINE");
        System.out.println("=================================================
");

        PatientMedicalFile patient = new PatientMedicalFile("PAT-849201", "Balaji Nemani", 28, 74.5);

        // Adding immutable prescriptions
        patient.addPrescription(new MedicationPrescription("Amoxicillin", "500 mg", 5));
        patient.addPrescription(new MedicationPrescription("Paracetamol", "650 mg", 3));
        patient.addPrescription(new MedicationPrescription("Vitamin D3", "60,000 IU", 8));

        patient.printMedicalAudit();

        // Testing Defensive Copying Security
        System.out.println("Testing external tampering with patient.getPrescriptions()...");
        try {
            List<MedicationPrescription> externalList = patient.getPrescriptions();
            externalList.add(new MedicationPrescription("Illegal_Narcotic", "100 mg", 10)); // Should throw error!
        } catch (UnsupportedOperationException e) {
            System.out.println("🛡️ SECURITY ALERT BLOCKED: External code cannot modify patient prescription list!");
            System.out.println("   (Defensive Copying prevented unauthorized medical record tampering)");
        }

        System.out.println("
=================================================");
        System.out.println("✅ Healthcare dossier remains 100% verified and secure!");
        System.out.println("=================================================");
    }
}
Terminal Output:
=================================================
🩺 ENTERPRISE HEALTHCARE EMR & AUDIT ENGINE
=================================================

-------------------------------------------------
🏥 APOLLO HEALTHCARE ELECTRONIC PATIENT DOSSIER
Patient ID:   PAT-849201
Full Name:    Balaji Nemani | Age: 28 yrs | Weight: 74.5 kg
Active Prescriptions (3):
  💊 Amoxicillin      | Dosage: 500 mg     | Course: 5 days
  💊 Paracetamol      | Dosage: 650 mg     | Course: 3 days
  💊 Vitamin D3       | Dosage: 60,000 IU  | Course: 8 days
-------------------------------------------------
Testing external tampering with patient.getPrescriptions()...
🛡️ SECURITY ALERT BLOCKED: External code cannot modify patient prescription list!
   (Defensive Copying prevented unauthorized medical record tampering)

=================================================
✅ Healthcare dossier remains 100% verified and secure!
=================================================

12. ప్రొడక్షన్ పిట్‌ఫాల్స్, బెస్ట్ ప్రాక్టీసెస్ & 5 క్విజ్‌లు (Best Practices & Quizzes)

🚫 ప్రొడక్షన్‌లో నివారించాల్సిన 4 ఘోరమైన తప్పులు (Production Pitfalls):

  1. ఫీల్డ్స్‌ను public గా ప్రకటించడం: ఇది ఎన్‌క్యాప్సులేషన్‌ను పూర్తిగా నాశనం చేస్తుంది. భవిష్యత్తులో వేలిడేషన్ లాజిక్ చేర్చాల్సి వస్తే మొత్తం ప్రాజెక్ట్ రీఫ్యాక్టర్ చేయాల్సి వస్తుంది.
  2. మ్యూటబుల్ ఆబ్జెక్టుల నేరుగా రిటర్న్ చేయడం (Reference Leak): Date లేదా List వంటి మ్యూటబుల్ ఆబ్జెక్టులను Getter లో నేరుగా ఇస్తే బయట ఉన్నవారు మీ ఆబ్జెక్ట్ స్టేట్‌ను మార్చేయగలరు. ఎల్లప్పుడూ Collections.unmodifiableList() లేదా డిఫెన్సివ్ క్లోన్‌ను వాడండి.
  3. సాధారణ DTOs కోసం అనవసరంగా 80 లైన్ల క్లాసులు రాయడం: కేవలం డేటాను మోసే ఆబ్జెక్టుల కోసం ఆధునిక జావా 14+ record ను వాడండి.
  4. Protected ని పబ్లిక్ తో సమానంగా భావించడం: protected కేవలం అదే ప్యాకేజీ మరియు వారసత్వ సబ్‌క్లాసులకు మాత్రమే. ప్రపంచం మొత్తానికి కాదు.

✨ ప్రొడక్షన్ గోల్డెన్ రూల్స్ (Golden Rules):

1. కనీస విజిబిలిటీ ప్రిన్సిపల్: ఫీల్డ్స్‌కు ఎల్లప్పుడూ సాధ్యమైనంత కఠినమైన యాక్సెస్ ఇవ్వండి (Start with private).
2. ఇమ్మ్యుటబిలిటీ ప్రాధాన్యత: మార్చాల్సిన అవసరం లేని ఫీల్డ్స్‌ను final చేయండి మరియు Setters ఇవ్వకండి.
3. Records for Data: REST API రిక్వెస్ట్/రెస్పాన్స్ పేలోడ్లకు ఎల్లప్పుడూ Java Records వాడండి.
4. డిఫెన్సివ్ కాపీలు: కన్‌స్ట్రక్టర్ ఇన్‌పుట్‌లో మరియు Getter అవుట్‌పుట్‌లో మ్యూటబుల్ ఆబ్జెక్టుల కాపీలను మాత్రమే ఉపయోగించండి.

🧠 మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes):

ప్రశ్న 1: ఎన్‌క్యాప్సులేషన్ (Encapsulation) సాధించడానికి ప్రాథమిక నియమం ఏమిటి?

సమాధానం: క్లాస్ ఫీల్డ్‌లను private గా ప్రకటించి (Data Hiding), వాటిని యాక్సెస్ చేయడానికి పబ్లిక్ Getters మరియు Setters ను అందించడం.

ప్రశ్న 2: ఒక వేరియబుల్ ముందు ఏ యాక్సెస్ మోడిఫైయర్ పేర్కొనకపోతే దానికి వర్తించే స్కోప్ ఏమిటి?

సమాధానం: Package-Private (Default). ఇది కేవలం అదే ప్యాకేజీలోని క్లాసులకు మాత్రమే కనిపిస్తుంది.

ప్రశ్న 3: డిఫెన్సివ్ కాపీయింగ్ (Defensive Copying) ఎందుకు చేయాలి?

సమాధానం: మ్యూటబుల్ ఆబ్జెక్ట్ రిఫరెన్స్‌లు (ఉదా: List, Date) బయటకు వెళ్ళినప్పుడు, బాహ్య కోడ్ మన క్లాస్ యొక్క అంతర్గత స్థితిని అనధికారికంగా మార్చకుండా కాపాడటానికి.

ప్రశ్న 4: Java Record లోని ఫీల్డ్స్ సహజంగా ఎలాంటి లక్షణాన్ని కలిగి ఉంటాయి?

సమాధానం: అవి సహజంగానే private final (100% Immutable) గా ఉంటాయి.

ప్రశ్న 5: Record లో 'title' అనే ఫీల్డ్ ఉంటే, దాని రీడర్ మెథడ్ పేరు ఏమిటి?

సమాధానం: title() (సాంప్రదాయ గెట్టర్ లాగా 'getTitle()' కాదు).

← మునుపటి పాఠం: 15. Constructors & this తర్వాతి పాఠం: 17. Inheritance & super Keyword →