Init Blocks, Cloning & Serialization
Static block { } class load hote hi ek baar chalta hai — static variables initialize karne ke liye best. Instance block har object banते waqt chalta hai (constructor se pehle).
clone() Object class ka method hai jo ek existing object ki copy bana deta hai (Cloneable interface implement karna padta hai).
Serializable interface implement karke object ko bytes mein convert kar sakte ho (jaise file mein save karna ya network par bhejna), aur baad mein deserialize karke wapas object bana sakte ho.
class Config implements Cloneable, Serializable {
static { System.out.println("Loaded once!"); }
int value = 10;
}Shallow clone (default clone() behavior, Object class se inherited) sirf top-level fields copy karta hai — agar field khud ek object (reference type) hai, dono clones us *same* nested object ko point karte hain (ek change karega to dusre mein bhi dikhega, kyunki reference copy hui hai, object nahi).
Deep clone nested objects ko bhi individually copy karta hai — poori tarah independent copy, lekin manually implement karna padta hai (har nested object ka bhi apna clone() call karna, recursively).
| Shallow Clone | Deep Clone | |
|---|---|---|
| Primitive fields | Copy hoti hain | Copy hoti hain |
| Reference fields (objects) | Same object share hota hai | Naya independent copy banta hai |
| Implement karna | Aasan (default clone()) | Manual, har nested object clone karna |
// Shallow: dono objects ka "address" field same object point karta hai
Person clone = original.clone();
clone.address.city = "Mumbai"; // original.address.city bhi change ho jaayega!Serialization ke waqt kuch fields skip karna ho (jaise password, ya kisi cache jo re-computable hai, ya koi field jo Serializable hi nahi hai jaise Thread), unhe transient mark karo — serialize hote waqt ye fields ignore ho jaate hain, aur deserialize hone par unki default value (0/null) milti hai.
class User implements Serializable {
String username;
transient String password; // serialize NAHI hoga
}Serializable class mein ek static final long serialVersionUID define karna best practice hai — ye ek "version number" hai jo batata hai class ka structure kaisa tha jab object serialize hua. Agar tum ise explicitly nahi likhte, JVM automatically compute kar deta hai (class ke structure se), lekin ye compiler/platform ke hisaab se badal sakta hai.
Agar baad mein class change ho jaaye (naya field add ho) aur purana serialized data deserialize karo, JVM serialVersionUID check karke incompatible version detect kar leta hai (InvalidClassException) — explicit UID rakhne se tum control karte ho ki kab "compatible" maana jaaye.
Jab class pehli baar load hoti hai: (1) static variables/blocks unke declaration order mein ek baar chalte hain (poore program mein sirf ek baar). Har baar jab "new" se object banta hai: (2) instance variables/blocks declaration order mein chalte hain, (3) fir constructor chalta hai.
Isliye static block sabse pehle (ek baar, class load par), instance block har object ke liye constructor se just pehle. Inheritance ke saath order aur interesting ho jaata hai — parent ke static blocks pehle, phir child ke static blocks, phir (object banते waqt) parent ke instance blocks + constructor, phir child ke.