Complete Deep Revision Guide β Backend Course ke liye
βββββββββββββββββββββββββββββββ
β CLASS (Blueprint) β
β βββββββββββββββββββββββ β
β β ClassName { β β
β β - fields (data) β β
β β - methods (code) β β
β β } β β
β βββββββββββββββββββββββ β
β β οΈ Class = NO MEMORY ALLOC β
β β οΈ Sirf TEMPLATE hai! β
βββββββββββββββββββββββββββββββ
β new keyword
βββββββββββββββββββββββββββββββ
β OBJECT (Instance) β
β βββββββββββββββββββββββ β
β β [Heap Memory] β β
β β β’ fields β values β β
β β β’ methods β code refβ β
β β β’ reference var β β β
β β Stack mein store β β
β βββββββββββββββββββββββ β
β β
Object = MEMORY ALLOC β
β β
Real data store hota haiβ
βββββββββββββββββββββββββββββββ
Class = Blueprint/Template | Object = Us blueprint se bana hua actual ghar
// Class define karna - ye sirf blueprint hai class Student { // Fields/Attributes (Instance Variables) String name; int rollNo; double marks; // Method/Behavior void displayInfo() { System.out.println("Name: " + name); System.out.println("Roll: " + rollNo); System.out.println("Marks: " + marks); } } public class ClassObject1 { public static void main(String[] args) { // Object create karna - Heap memory allocate hoti hai Student s1 = new Student(); // s1 β reference variable (Stack) // Fields ko value assign karna s1.name = "Rahul"; s1.rollNo = 101; s1.marks = 85.5; // Method call karna s1.displayInfo(); // Second object - alag memory location! Student s2 = new Student(); s2.name = "Priya"; s2.rollNo = 102; s2.marks = 92.0; s2.displayInfo(); } }
s1 aur s2 alag-alag objects hain! Heap mein do different memory blocks bante hain. Reference variable Stack mein rehta hai jo Heap address point karta hai.class Book { String title; String author; int pages; void showDetails() { System.out.println(title + " by " + author + " (" + pages + " pages)"); } } public class ClassObject2 { public static void main(String[] args) { // Reference variable declare kiya, par object nahi banaya Book b1; // b1 = null (default value) // b1.showDetails(); β NullPointerException dega! // Ab object create karte hain b1 = new Book(); b1.title = "Java Complete Reference"; b1.author = "Herbert Schildt"; b1.pages = 1200; b1.showDetails(); // Array of Objects Book[] library = new Book[3]; // 3 references, sab null library[0] = new Book(); library[0].title = "Effective Java"; library[0].author = "Joshua Bloch"; library[0].pages = 416; library[1] = new Book(); library[1].title = "Head First Java"; library[1].author = "Kathy Sierra"; library[1].pages = 720; // library[2] abhi bhi null hai! System.out.println("\nLibrary Contents:"); for(int i = 0; i < library.length; i++) { if(library[i] != null) { library[i].showDetails(); } else { System.out.println("Slot " + i + " is empty (null)"); } } } }
references create hote hain, actual objects nahi! Har index pe alag se new karna padta hai.class Account { String accNo; double balance; void deposit(double amount) { balance += amount; System.out.println("Deposited: " + amount + ", New Balance: " + balance); } } public class ClassObject3 { public static void main(String[] args) { Account acc1 = new Account(); acc1.accNo = "ACC001"; acc1.balance = 1000; // Reference copy - SAME object, alag reference variable Account acc2 = acc1; // acc2 bhi same heap location point kar raha! System.out.println("Before: acc1.balance = " + acc1.balance); acc2.deposit(500); // acc2 se call kiya System.out.println("After: acc1.balance = " + acc1.balance); // ^ acc1 bhi change ho gaya! Kyunki SAME object hai System.out.println("\nacc1 == acc2: " + (acc1 == acc2)); // true! // NEW object create karna - alag memory Account acc3 = new Account(); acc3.accNo = "ACC002"; acc3.balance = 2000; System.out.println("\nacc1 == acc3: " + (acc1 == acc3)); // false! acc3.deposit(300); System.out.println("acc1.balance: " + acc1.balance); // unchanged System.out.println("acc3.balance: " + acc3.balance); // changed } }
Account acc2 = acc1; β Object COPY nahi hota! Sirf reference copy hota hai. Dono variables SAME object ko point karte hain. New object ke liye new keyword zaroori hai!class Data { int value; Data(int v) { value = v; } } public class ClassObject4 { // Primitive type parameter - PASS BY VALUE static void modifyPrimitive(int x) { x = x * 10; System.out.println("Inside method (primitive): " + x); } // Object reference parameter - PASS BY VALUE OF REFERENCE static void modifyObject(Data d) { d.value = d.value * 10; // Original object modify! System.out.println("Inside method (object field): " + d.value); } // Object reference ko reassign karna static void reassignReference(Data d) { d = new Data(999); // New object, local reference change System.out.println("Inside method (reassigned): " + d.value); } public static void main(String[] args) { // Primitive test int num = 5; System.out.println("Before primitive: " + num); modifyPrimitive(num); System.out.println("After primitive: " + num + " (unchanged!)"); // Object field modify test Data obj = new Data(5); System.out.println("\nBefore object field: " + obj.value); modifyObject(obj); System.out.println("After object field: " + obj.value + " (CHANGED!)"); // Reference reassign test Data obj2 = new Data(5); System.out.println("\nBefore reassign: " + obj2.value); reassignReference(obj2); System.out.println("After reassign: " + obj2.value + " (unchanged!)"); } }
class Temp { String name; Temp(String n) { name = n; System.out.println("π’ Constructor: " + name + " created"); } // Finalize - deprecated but for demo (GC se pehle call hota tha) protected void finalize() { System.out.println("π΄ Finalize: " + name + " being garbage collected"); } void show() { System.out.println("Object: " + name); } } public class ClassObject5 { public static void main(String[] args) { // Object creation Temp t1 = new Temp("Alpha"); t1.show(); // Reference null karna - object eligible for GC t1 = null; // "Alpha" object ab unreachable! System.out.println("t1 set to null - Alpha eligible for GC"); // New object same reference variable mein t1 = new Temp("Beta"); t1.show(); // Scope ke bahar jaane par automatic GC eligible { Temp t2 = new Temp("Gamma"); t2.show(); } // t2 scope khatam - Gamma eligible for GC System.out.println("t2 scope ended - Gamma eligible for GC"); // GC suggest karna (guarantee nahi!) System.out.println("\nRequesting GC (no guarantee)..."); System.gc(); // Thoda wait for GC to potentially run try { Thread.sleep(100); } catch(Exception e) {} System.out.println("\nProgram ending..."); // t1 ("Beta") bhi ab GC eligible hoga jab program end hoga } }
obj = null; β explicit dereferenceSystem.gc() sirf suggestion hai, guarantee nahi
1. new ClassName() call hota hai
β
2. Heap memory allocate hoti hai object ke liye
β
3. DEFAULT values assign hoti hain (0, null, false)
β
4. CONSTRUCTOR execute hota hai β custom initialization
β
5. Reference variable ko heap address return hota hai
βββββββββββββββββββββββββββββββ
β Constructor Rules: β
β β’ Name = Class name EXACT β
β β’ NO return type (not even void)β
β β’ Automatically called with new β
β β’ Agar khud na likho β Default constructor milta haiβ
β β’ Parameterized likha β Default NAHI milta! β
βββββββββββββββββββββββββββββββ
class Employee { String name; int id; double salary; // πΉ Default Constructor (No-arg) Employee() { System.out.println("π¦ Default constructor called"); name = "Unknown"; id = 0; salary = 0.0; } // πΉ Parameterized Constructor Employee(String n, int i, double s) { System.out.println("π¦ Parameterized constructor called"); name = n; // this.name = n; bhi likh sakte the id = i; salary = s; } void display() { System.out.println(name + " (ID:" + id + ") - βΉ" + salary); } } public class Constructor1 { public static void main(String[] args) { System.out.println("=== Creating with default constructor ==="); Employee e1 = new Employee(); // Default constructor call e1.display(); System.out.println("\n=== Creating with parameterized constructor ==="); Employee e2 = new Employee("Amit", 101, 50000); // Parameterized e2.display(); System.out.println("\n=== Creating another with default ==="); Employee e3 = new Employee(); e3.name = "Priya"; // Manual assignment after default init e3.id = 102; e3.salary = 45000; e3.display(); } }
class Rectangle { double length, width; // πΉ No-arg: Square with side 1 Rectangle() { length = width = 1.0; System.out.println("β¬ Default: 1x1 square"); } // πΉ Single param: Square with given side Rectangle(double side) { length = width = side; System.out.println("β¬ Square: " + side + "x" + side); } // πΉ Two params: Rectangle Rectangle(double l, double w) { length = l; width = w; System.out.println("β Rectangle: " + l + "x" + w); } double area() { return length * width; } } public class Constructor2 { public static void main(String[] args) { Rectangle r1 = new Rectangle(); // Calls no-arg System.out.println("Area: " + r1.area() + "\n"); Rectangle r2 = new Rectangle(5); // Calls single-param System.out.println("Area: " + r2.area() + "\n"); Rectangle r3 = new Rectangle(4, 6); // Calls two-param System.out.println("Area: " + r3.area() + "\n"); // Compiler decides which constructor based on arguments! // Ye hai Constructor Overloading } }
class Product { String name; int id; double price; String category; // πΉ Master constructor - saara kaam yahan Product(String n, int i, double p, String c) { System.out.println("π Master constructor"); name = n; id = i; price = p; category = c; } // πΉ 3-param β master ko call Product(String n, int i, double p) { this(n, i, p, "General"); // this() must be FIRST line! System.out.println("π 3-param constructor"); } // πΉ 2-param β 3-param ko call Product(String n, int i) { this(n, i, 0.0); // Chain: 2β3β4 param System.out.println("π 2-param constructor"); } // πΉ No-arg β 2-param ko call Product() { this("NoName", 0); System.out.println("π No-arg constructor"); } void show() { System.out.println(name + " #" + id + " βΉ" + price + " [" + category + "]"); } } public class Constructor3 { public static void main(String[] args) { System.out.println("=== Chain: No-arg β 2 β 3 β 4 ==="); Product p1 = new Product(); p1.show(); System.out.println("\n=== Chain: 2-param β 3 β 4 ==="); Product p2 = new Product("Laptop", 101); p2.show(); System.out.println("\n=== Direct 4-param ==="); Product p3 = new Product("Phone", 102, 25000, "Electronics"); p3.show(); } }
this(...) se dusre constructor call karothis() MUST be FIRST statement in constructor// πΉ Case 1: No constructor likha β Compiler default deta hai class Case1 { int x; // Compiler automatically adds: Case1() { super(); } } // πΉ Case 2: Khud parameterized likha β Default NAHI milega! class Case2 { int x; Case2(int val) { x = val; } // β Ab Case2() constructor nahi hai! // new Case2(); β Compile Error! } // πΉ Case 3: Khud default bhi likh do β dono milenge class Case3 { int x; Case3() { x = 0; System.out.println("Default"); } Case3(int val) { x = val; System.out.println("Param"); } } public class Constructor4 { public static void main(String[] args) { // Case 1: Default constructor available Case1 c1 = new Case1(); // β Works System.out.println("Case1 x = " + c1.x); // 0 (default int value) // Case 2: Only parameterized exists Case2 c2 = new Case2(100); // β Works System.out.println("Case2 x = " + c2.x); // Case2 c3 = new Case2(); β Compile Error! // Case 3: Both constructors available Case3 c3a = new Case3(); // β Default Case3 c3b = new Case3(200); // β Parameterized } }
class Address { String city, state; Address(String c, String s) { city = c; state = s; } void show() { System.out.print(city + ", " + state); } } class Person { String name; Address addr; // Object as field - Composition // Constructor mein Object parameter Person(String n, Address a) { name = n; addr = a; // Reference copy, not deep copy! } void display() { System.out.print(name + " lives in "); addr.show(); System.out.println(); } } public class Constructor5 { public static void main(String[] args) { // Address object pehle banao Address home = new Address("Mumbai", "Maharashtra"); // Address object ko Person constructor mein pass karo Person p1 = new Person("Rahul", home); p1.display(); // β οΈ Reference sharing - same Address object! Person p2 = new Person("Priya", home); p2.display(); // home change karo β dono Person affect honge! System.out.println("\nChanging address..."); home.city = "Pune"; p1.display(); // Rahul bhi Pune show karega! p2.display(); } }
βββββββββββββββββββββββββββββββ β this = Current Object Reference β β β’ Har non-static method ke andar β β implicitly available hota hai β β β’ Heap mein jo current object β β chal raha hai, uska address β β β’ Static methods mein this β β βββββββββββββββββββββββββββββββ Use Cases: 1οΈβ£ Parameter vs Field name conflict resolve 2οΈβ£ Constructor chaining: this(...) 3οΈβ£ Current object return karna 4οΈβ£ Current object as method argument pass karna 5οΈβ£ Anonymous object se method call
class User { String username; int age; // πΉ Problem: Parameter name same as field User(String username, int age) { // username = username; β Field ko assign nahi hoga! // Local parameter ko hi local parameter assign hoga // β Solution: this se field refer karo this.username = username; // LHS: field, RHS: parameter this.age = age; System.out.println("User created: " + this.username); } void greet() { // this optional hai jab conflict nahi hai System.out.println("Hi, I'm " + username); System.out.println("Age: " + this.age); // this likh sakte hain } // πΉ Method chaining ke liye this return karna User setAge(int age) { this.age = age; return this; // Current object return } } public class ThisKeyword1 { public static void main(String[] args) { User u1 = new User("coder123", 25); u1.greet(); // Method chaining using this return User u2 = new User("dev456", 30); u2.setAge(31).greet(); // setAge returns this, then greet() call } }
class Mobile { String brand, model; int storage; double price; // Master constructor Mobile(String b, String m, int s, double p) { brand = b; model = m; storage = s; price = p; System.out.println("π Master: " + brand + " " + model); } // this() se constructor call - MUST be first line Mobile(String b, String m, int s) { this(b, m, s, 0.0); // β First line! System.out.println("π 3-param constructor"); } Mobile(String b, String m) { this(b, m, 128); // β Calls 3-param β which calls master System.out.println("π 2-param constructor"); } // β Galat: this() first line nahi hai // Mobile(String b) { // System.out.println("Start"); // this(b, "Unknown"); β Compile Error! // } void show() { System.out.printf("%s %s | %dGB | βΉ%.2f\n", brand, model, storage, price); } } public class ThisKeyword2 { public static void main(String[] args) { System.out.println("=== 4-param direct ==="); Mobile m1 = new Mobile("Apple", "iPhone15", 256, 79999); m1.show(); System.out.println("\n=== 3-param β chain ==="); Mobile m2 = new Mobile("Samsung", "S24", 512); m2.show(); System.out.println("\n=== 2-param β chain β chain ==="); Mobile m3 = new Mobile("OnePlus", "12R"); m3.show(); } }
class Team { String name; Team(String n) { name = n; } // πΉ Current object ko as argument pass karna void invite(Team other) { System.out.println(this.name + " invites " + other.name); } // πΉ Current object return karna (Fluent API) Team getPartner(Team partner) { System.out.println(this.name + " + " + partner.name + " = Team Up!"); return partner; // ya return this; bhi kar sakte the } } class GameManager { // πΉ Object accept karne wala method static void registerTeam(Team t) { System.out.println("β Registered: " + t.name); } } public class ThisKeyword3 { public static void main(String[] args) { Team t1 = new Team("Warriors"); Team t2 = new Team("Champions"); // this as argument: current object pass to another object's method t1.invite(t2); // Warriors invites Champions t2.invite(t1); // Champions invites Warriors // this return: method chaining System.out.println(); t1.getPartner(t2).invite(t1); // getPartner returns t2, then t2.invite(t1) // Passing current object to static method System.out.println(); GameManager.registerTeam(t1); // Explicit GameManager.registerTeam(this); // β Error! static context mein this nahi } }
this use nahi kar sakteclass Calculator { int result = 0; Calculator add(int x) { result += x; return this; // Fluent chaining } int getResult() { return result; } // πΉ Current object ko compare karna boolean isSame(Calculator other) { return this == other; // Reference comparison } } public class ThisKeyword4 { public static void main(String[] args) { // πΉ Anonymous object - reference variable nahi, direct use int val = new Calculator().add(10).add(20).getResult(); System.out.println("Anonymous chain result: " + val); // πΉ Anonymous object as method argument Calculator calc1 = new Calculator(); calc1.add(5); // Anonymous object pass to method boolean same = calc1.isSame(new Calculator()); // false - different objects System.out.println("Same object? " + same); // πΉ this return se chaining Calculator calc2 = new Calculator(); calc2.add(1).add(2).add(3); // add() returns this System.out.println("Chained result: " + calc2.getResult()); // πΉ Anonymous with immediate method call System.out.println("One-liner: " + new Calculator().add(100).getResult()); } }
new ClassName() bina reference variable ke = Anonymous objectnew Calc().add(5)class Parent { String name = "Parent"; void show() { System.out.println("Parent show: " + name); } } class Child extends Parent { String name = "Child"; // Field hiding void show() { // Method overriding System.out.println("Child show: " + name); // Child's name System.out.println("this.name: " + this.name); // Child's name System.out.println("super.name: " + super.name); // Parent's name this.show(); // Child's show (recursive! careful) // super.show(); // Parent's show call kar sakte the } Child() { // super(); implicitly called first by compiler System.out.println("Child constructor"); } Child(String n) { super(); // β Explicit super() call - must be first this.name = n; // this se current class field } } public class ThisKeyword5 { public static void main(String[] args) { Child c = new Child("Little"); System.out.println("\n=== Accessing fields ==="); System.out.println("c.name: " + c.name); // Child's (hiding) System.out.println("((Parent)c).name: " + ((Parent)c).name); // Parent's via casting System.out.println("\n=== Calling methods ==="); c.show(); // Overridden method - Child's version // ((Parent)c).show(); // Parent's version call kar sakte the } }
this.field β Current class ka field (hiding case mein)super.field β Parent class ka fieldthis.method() β Current class ka method (overriding case)super.method() β Parent class ka overridden methodthis(...) β Same class ka constructorsuper(...) β Parent class ka constructorthis.show() inside show() = infinite recursion! Use super.show() to call parent versionβββββββββββββββββββββββββββββββ β Method Types: β βββββββββββββββββββββββββββββββ€ β πΉ Instance Method β β β’ Object ke through call β β β’ this available β β β’ Instance vars access β β β β πΉ Static Method β β β’ Class ke through call β β β’ this β not available β β β’ Only static vars β β β β πΉ Varargs Method β β β’ Variable arguments β β β’ type... paramName β β β’ Internally array β βββββββββββββββββββββββββββββββ Method Overloading = Same name, DIFFERENT parameters β’ Compile-time polymorphism β’ Return type alone se overload nahi hota! β’ Compiler: argument count + type + order dekhta hai
class Counter { // Instance variable - har object ka alag int instanceCount = 0; // Static variable - sab objects share karte hain static int staticCount = 0; // πΉ Instance Method void incrementInstance() { instanceCount++; staticCount++; // Instance method static bhi access kar sakta System.out.println("Instance: " + instanceCount + ", Static: " + staticCount); } // πΉ Static Method static void incrementStatic() { staticCount++; // instanceCount++; β Error! Static can't access instance directly System.out.println("Static only: " + staticCount); } // πΉ Static method mein instance access kaise karein? static void accessViaObject(Counter c) { c.instanceCount++; // β Object reference se access kar sakte System.out.println("Via object: " + c.instanceCount); } } public class Method1 { public static void main(String[] args) { // Static method call - class name se Counter.incrementStatic(); // β Preferred // new Counter().incrementStatic(); // β Works but not preferred // Instance method call - object se hi Counter c1 = new Counter(); c1.incrementInstance(); // β instanceCount=1, staticCount=1 Counter c2 = new Counter(); c2.incrementInstance(); // β instanceCount=1 (new object), staticCount=2 System.out.println("\nc1.instanceCount: " + c1.instanceCount); // 1 System.out.println("c2.instanceCount: " + c2.instanceCount); // 1 System.out.println("Counter.staticCount: " + Counter.staticCount); // 2 // Static method se instance access via object Counter.accessViaObject(c1); // c1.instanceCount becomes 2 System.out.println("After static call: c1.instanceCount = " + c1.instanceCount); } }
ClassName.method()class Printer { // πΉ Overload 1: No param void print() { System.out.println("[No Data]"); } // πΉ Overload 2: int param void print(int n) { System.out.println("Integer: " + n); } // πΉ Overload 3: double param (different type) void print(double d) { System.out.println("Double: " + d); } // πΉ Overload 4: String param void print(String s) { System.out.println("String: " + s); } // πΉ Overload 5: int + String (different count + type) void print(int n, String s) { System.out.println("Int+String: " + n + " - " + s); } // πΉ Overload 6: String + int (order matters!) void print(String s, int n) { System.out.println("String+Int: " + s + " - " + n); } // β Ye overload nahi hai - sirf return type different! // String print(int n) { return ""+n; } β Compile Error! } public class Method2 { public static void main(String[] args) { Printer p = new Printer(); // Compiler decide karega kaunsa method call karna hai // Based on: argument count + type + order p.print(); // Calls print() p.print(42); // Calls print(int) p.print(3.14); // Calls print(double) p.print("Hello"); // Calls print(String) p.print(100, "Score"); // Calls print(int, String) p.print("Rank", 1); // Calls print(String, int) // πΉ Type Promotion in Overloading byte b = 10; p.print(b); // byte β int promotion β print(int) call hoga // πΉ Ambiguity - Compiler confuse! // p.print(null); β Compile Error! print(String) or print(int[])? } }
print(null) ambiguous ho sakta hai agar multiple reference types hainclass MathUtils { // πΉ Varargs method: type... name = array internally static int sum(int... numbers) { // numbers is actually int[] array int total = 0; for (int n : numbers) { total += n; } return total; } // πΉ Varargs with other parameters - varargs MUST be last static String join(String separator, String... words) { if (words.length == 0) return ""; StringBuilder sb = new StringBuilder(words[0]); for (int i = 1; i < words.length; i++) { sb.append(separator).append(words[i]); } return sb.toString(); } // β Galat: varargs last mein nahi hai // static void wrong(int... nums, String s) {} β Compile Error! // πΉ Overloading with varargs static void display(String msg) { System.out.println("Single: " + msg); } static void display(String... msgs) { System.out.print("Varargs: "); for(String m : msgs) System.out.print(m + " "); System.out.println(); } } public class Method3 { public static void main(String[] args) { // πΉ Varargs: 0, 1, or multiple arguments System.out.println("Sum of []: " + MathUtils.sum()); // 0 args System.out.println("Sum of [5]: " + MathUtils.sum(5)); // 1 arg System.out.println("Sum of [1,2,3]: " + MathUtils.sum(1,2,3)); // multiple // πΉ Array bhi pass kar sakte hain varargs mein int[] arr = {10, 20, 30}; System.out.println("Sum of array: " + MathUtils.sum(arr)); // πΉ Varargs with other params System.out.println("\nJoin: " + MathUtils.join("-", "Java", "is", "awesome")); System.out.println("Join (1 word): " + MathUtils.join(",", "Solo")); // πΉ Overloading: String vs String... - which one calls? MathUtils.display("Hello"); // Calls display(String) - more specific! MathUtils.display("A", "B"); // Calls display(String...) - only option } }
type... paramName (three dots)method(arr)class Box { int value; Box(int v) { value = v; } } public class Method4 { // πΉ Primitive: Pass by Value - copy of value static void modifyPrimitive(int x) { x = 999; System.out.println("Inside primitive: " + x); } // πΉ Object Reference: Pass by Value OF Reference // Reference ki copy pass hoti hai, not the reference itself static void modifyObjectField(Box b) { b.value = 999; // β Original object modify - same heap location System.out.println("Inside object field: " + b.value); } // πΉ Reassigning the reference parameter static void reassignReference(Box b) { b = new Box(777); // β New object, local reference change only System.out.println("Inside reassign: " + b.value); // Original reference unaffected! } // πΉ Swapping objects - doesn't work like you think! static void trySwap(Box a, Box b) { Box temp = a; a = b; b = temp; System.out.println("Inside swap: a=" + a.value + ", b=" + b.value); // Original references unchanged! } public static void main(String[] args) { // Primitive test int num = 10; System.out.println("Before primitive: " + num); modifyPrimitive(num); System.out.println("After primitive: " + num + " (unchanged)\n"); // Object field modify test Box box1 = new Box(10); System.out.println("Before object field: " + box1.value); modifyObjectField(box1); System.out.println("After object field: " + box1.value + " (CHANGED!)\n"); // Reference reassign test Box box2 = new Box(10); System.out.println("Before reassign: " + box2.value); reassignReference(box2); System.out.println("After reassign: " + box2.value + " (unchanged!)\n"); // Swap attempt Box x = new Box(100), y = new Box(200); System.out.println("Before swap: x=" + x.value + ", y=" + y.value); trySwap(x, y); System.out.println("After swap: x=" + x.value + ", y=" + y.value + " (unchanged!)"); } }
class Builder { StringBuilder sb = new StringBuilder(); // πΉ Fluent API: Return this for chaining Builder append(String s) { sb.append(s); return this; // Return current object } Builder append(int n) { sb.append(n); return this; } // πΉ Return new object (Factory pattern) static Builder create() { return new Builder(); } // πΉ Return different type String build() { return sb.toString(); } // πΉ Return object based on condition static Builder fromTemplate(String template) { Builder b = new Builder(); if (template.equals("greet")) { b.sb.append("Hello, "); } else if (template.equals("farewell")) { b.sb.append("Goodbye, "); } return b; } } public class Method5 { public static void main(String[] args) { // πΉ Fluent chaining with returned 'this' String result1 = Builder.create() .append("Java ") .append("is ") .append("awesome") .append("!") .build(); System.out.println(result1); // πΉ Factory method returning object String greet = Builder.fromTemplate("greet") .append("World") .build(); System.out.println(greet); String bye = Builder.fromTemplate("farewell") .append("Java") .build(); System.out.println(bye); // πΉ Method returning object stored in variable Builder b = Builder.create(); b.append("Stored ").append(123); System.out.println(b.build()); } }
this β Fluent API / Method chainingthis se external code bhi object modify kar sakta hai - encapsulation break ho sakta haiββββββββββββββ¬ββββββββββ¬ββββββββββ¬ββββββββββ¬ββββββββββ β Modifier β Class β Package β Subclassβ World β ββββββββββββββΌββββββββββΌββββββββββΌββββββββββΌββββββββββ€ β private β β β β β β β β β β (default) β β β β β β* β β β β protected β β β β β β β β β β public β β β β β β β β β ββββββββββββββ΄ββββββββββ΄ββββββββββ΄ββββββββββ΄ββββββββββ *default: subclass in SAME package only
class BankAccount { private double balance; // π Outside class se direct access nahi public BankAccount(double initial) { balance = initial; } // π Controlled access via public methods public void deposit(double amount) { if (amount > 0) balance += amount; } public double getBalance() { return balance; // Read-only access } // πΉ Private method - only usable inside this class private boolean isValid(double amount) { return amount > 0 && amount <= 100000; } } public class Access1 { public static void main(String[] args) { BankAccount acc = new BankAccount(1000); acc.deposit(500); // β Public method System.out.println("Balance: βΉ" + acc.getBalance()); // β // acc.balance = 999999; β Compile Error: private // acc.isValid(100); β Compile Error: private method } }
private rakhopublic getter/setters doprivate rakho// File: pkg1/Parent.java package pkg1; public class Parent { protected int protectedValue = 100; protected void show() { System.out.println("Protected: " + protectedValue); } } // File: pkg1/Child.java (same package) package pkg1; public class Child extends Parent { public void access() { protectedValue = 200; // β Same package + subclass show(); // β } } // File: pkg2/Other.java (different package, not subclass) package pkg2; import pkg1.Parent; public class Other { public static void main(String[] args) { Parent p = new Parent(); // p.protectedValue = 50; β Error: not subclass + different package // p.show(); β Error } } // File: pkg2/Sub.java (different package, IS subclass) package pkg2; import pkg1.Parent; public class Sub extends Parent { public void test() { // protectedValue = 300; β Can access ONLY via inheritance super.protectedValue = 300; // β Via super/this super.show(); // β Parent p = new Parent(); // p.protectedValue = 400; β Can't access via different package reference } }
| Concept | Key Points |
|---|---|
| Class | Blueprint | No memory | Contains fields + methods | Template for objects |
| Object | Instance of class | Heap memory | Created with new | Has state + behavior |
| Constructor | Same name as class | No return type | Auto-called with new | Overloading possible |
this | Current object reference | Field conflict resolve | Constructor chaining | Method chaining |
| Instance Method | Object se call | Access instance+static | this available |
| Static Method | Class se call | Only static access | this β | Utility methods |
| Overloading | Same name, diff params | Compile-time polymorphism | Return type alone β overload |
| Access Modifiers | private < default < protected < public | Encapsulation ke liye use |
| Encapsulation | private fields + public getters/setters | Data hiding + validation |
| Pass-by-Value | Java ALWAYS pass-by-value | Object: reference ki value copy | Field modify = original affect |
1οΈβ£ Class Design: β’ Single Responsibility Principle - Ek class = Ek kaam β’ Meaningful class/method names - Self-documenting code β’ Keep classes small and focused 2οΈβ£ Encapsulation: β’ Fields β private β’ Access β public getters/setters with validation β’ Expose minimum API surface 3οΈβ£ Constructors: β’ Use constructor chaining for code reuse β’ Validate parameters in constructor β’ Consider Builder pattern for complex objects 4οΈβ£ Methods: β’ Keep methods small (single responsibility) β’ Use meaningful parameter names β’ Prefer immutable objects where possible β’ Document with JavaDoc 5οΈβ£ Memory Management: β’ Null references explicitly when done β’ Avoid memory leaks in collections β’ Use try-with-resources for AutoCloseable 6οΈβ£ Thread Safety (Backend Critical): β’ Immutable objects are thread-safe by default β’ Synchronize shared mutable state β’ Prefer concurrent collections 7οΈβ£ Testing: β’ Design classes to be testable (dependency injection) β’ Avoid static state in business logic β’ Use interfaces for mocking
// πΉ Well-designed backend entity class public final class User { // final = immutable, thread-safe // π Private final fields - immutable after construction private final String userId; private final String email; private final String passwordHash; // Never store plain password! private final UserRole role; // πΉ Private constructor - force use of Builder private User(Builder builder) { this.userId = validateNotEmpty(builder.userId, "userId"); this.email = validateEmail(builder.email); this.passwordHash = builder.passwordHash; // Already hashed this.role = builder.role != null ? builder.role : UserRole.USER; } // πΉ Public getters - NO setters (immutable) public String getUserId() { return userId; } public String getEmail() { return email; } public UserRole getRole() { return role; } // πΉ Business logic methods public boolean hasRole(UserRole required) { return this.role.getLevel() >= required.getLevel(); } public boolean verifyPassword(String plainPassword, PasswordEncoder encoder) { return encoder.matches(plainPassword, this.passwordHash); } // πΉ Helper validation methods (private) private static String validateNotEmpty(String value, String fieldName) { if (value == null || value.isBlank()) { throw new IllegalArgumentException(fieldName + " cannot be empty"); } return value; } private static String validateEmail(String email) { // Simple email validation - use library in production if (!email.matches(".+@.+\\..+")) { throw new IllegalArgumentException("Invalid email"); } return email.toLowerCase(); // Normalize } // πΉ Builder Pattern for flexible object creation public static class Builder { private String userId, email, passwordHash; private UserRole role; public Builder userId(String id) { this.userId = id; return this; } public Builder email(String email) { this.email = email; return this; } public Builder passwordHash(String hash) { this.passwordHash = hash; return this; } public Builder role(UserRole role) { this.role = role; return this; } public User build() { return new User(this); // Private constructor access } } // πΉ Override Object methods for proper behavior @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return userId.equals(user.userId); // Business key } @Override public int hashCode() { return userId.hashCode(); } @Override public String toString() { return "User{userId='" + userId + "', email='" + email + "', role=" + role + '}'; } } // πΉ Usage Example public class FinalExample { public static void main(String[] args) { // β Builder pattern - readable, flexible, validated User admin = new User.Builder() .userId("admin001") .email("admin@company.com") .passwordHash("$2a$10$...hashed...") .role(UserRole.ADMIN) .build(); System.out.println(admin); System.out.println("Is admin? " + admin.hasRole(UserRole.ADMIN)); // β This won't compile - immutable! // admin.email = "hacked@evil.com"; // Compile Error } } enum UserRole { USER(1), MODERATOR(2), ADMIN(3); private final int level; UserRole(int l) { level = l; } public int getLevel() { return level; } }
public class User β File: User.java