Java mein Data-Oriented Programming: Ek Naya Paradigm Aur Tumhare Placement Code Pe Iska Real Impact
Author: Divyansh Bhardwaj (github.com/dbc2201) Date: April 7, 2026 Read time: ~10 minutes Prerequisite: Basic Java OOP comfort; Records aur Sealed Classes ka naam suna ho
- Problem — Boilerplate Overload
- OOP Ne Incomplete Picture Di
- DOP Kya Hai
- Java Ka DOP Toolkit — Teen Amigos
- Real Example: OOP vs DOP Side-by-Side
- DOP vs OOP — Kab Kya Use Karein
- 2026 Mein Kya Naya Hai — Carrier Classes
- Placement-Ready Code: Java 21 Pe Aaj Se Start Karo
- Closing Thought
- Resources
Sochо — tumhara last semester ka Java project kuch aisa dikhta tha:
UserDTO → UserVO → UserMapper → UserResponse → UserBuilder
Ek User ke liye paanch classes.
Har class mein getters, setters, equals(), hashCode().
Aur phir bhi koi nahi bata sakta tha ki us object ki actual state kya thi runtime pe.
Agar yeh relatable laga — toh yeh blog tumhare liye hai.
OOP ne ek powerful idea diya: state aur behavior ko saath rakhao.
User object ke andar login() bhi hoga, getAddress() bhi hoga, updateProfile() bhi hoga.
Real systems mein yeh model kaam karta hai — jab objects genuinely behavior-rich hote hain.
Lekin modern software ka ek bada hissa kuch aur hai: data ko ek jagah se doosri jagah carry karna. REST API response, event payload, database row, gRPC message — inhe behavior nahi chahiye. Inhe sirf accurate, immutable, type-safe data representation chahiye.
Aur usi gap ke liye OOP ka toolbox thoda insufficient feel hota hai.
Data-Oriented Programming (DOP) ka pitch simple hai:
Data ko pehle socho. Behavior ko baad mein, alag rakhо. Aur data ko immutable banao.
Brian Goetz — Java Language Architect at Oracle — ne June 2022 mein formally Java ke liye describe kiya.
| # | Principle | Matlab |
|---|---|---|
| 1 | Data is immutable | Ek baar banao, phir change mat karo |
| 2 | Model the data, the whole data, and nothing but the data | Sirf wahi represent karo jo zaruri hai |
| 3 | Make illegal states unrepresentable | Invalid combinations ko type system se hi rokao |
| 4 | Separate operations from data | Behavior ko data ke structure ke andar mat cramming karo |
Important: DOP, OOP ko replace nahi karta — yeh data modeling layer ke liye ek better lens hai. OOP bilkul valid rehta hai apni jagah pe. Section 6 mein clearly delineate kiya gaya hai.
Java 21 (current LTS) mein teen features hain jo milke DOP enable karte hain. Inhe Project Amber kehte hain — aur yeh teen ek dusre ke saath designed hain.
// Traditional approach — ~20 lines
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
@Override public boolean equals(Object o) { /* ... */ }
@Override public int hashCode() { /* ... */ }
@Override public String toString() { /* ... */ }
}
// Record — ek line
record Point(int x, int y) {}Record compiler ko clearly bolta hai: "yeh class sirf data carry karne ke liye hai."
Automatic equals(), hashCode(), toString(), aur canonical constructor — sab milta hai.
Placement Interview Gotcha — Accessor Naming
Records JavaBeans convention follow nahi karte. Accessor
x()hoga —getX()nahi.Point p = new Point(3, 4); p.x(); // ✅ correct record accessor p.getX(); // ❌ compile error — getX() record mein exist nahi kartaSpring aur JPA background wale developers yahan commonly trip karte hain.
Records kab use karein: DTOs, API responses, value objects, event payloads — koi bhi class jo sirf data carry kare.
Records kab use na karein:
JPA/Hibernate Entities ke liye Records mat use karo. JPA ko no-arg constructor chahiye aur mutable state chahiye — records dono disallow karte hain. Database entities ke liye traditional classes use karo. Records ka use karo DTO layer mein — entity layer mein nahi.
// Traditional — compiler ko koi guarantee nahi
class Order {
String status; // "pending"? "PENDING"? "Pending "? koi typo?
}
// DOP — compiler enforce karta hai
sealed interface OrderStatus
permits Pending, Shipped, Delivered, Cancelled {}
record Pending(LocalDateTime placedAt) implements OrderStatus {}
record Shipped(String trackingId, LocalDateTime shippedAt) implements OrderStatus {}
record Delivered(LocalDateTime deliveredAt) implements OrderStatus {}
record Cancelled(String reason) implements OrderStatus {}Ab ek Shipped order ke paas trackingId hoga hi.
Koi null check nahi. Koi status.equals("SHIPPED") nahi.
Invalid state banana chahо — compile time pe rokega.
// Production code mein financial values ke liye BigDecimal preferred hoti hai
double calculateDiscount(OrderStatus status) {
return switch (status) {
case Pending p -> 0.0;
case Shipped s -> 0.05;
case Delivered d -> 0.10;
case Cancelled c -> 0.0;
};
}Koi default case nahi — yeh deliberate hai.
Agar kal koi naya OrderStatus add karo, compiler turant batayega ki yahan handle nahi hua.
Yeh exhaustiveness — aur placement interviews mein exactly yahi concept interviewers dekhna chahte hain.
Ek notification system banate hain — Email, SMS, Push.
class Notification {
private String type; // "EMAIL" | "SMS" | "PUSH"
private String recipient;
private String subject; // sirf email ke liye — SMS mein null
private String phoneNumber; // sirf SMS ke liye — email mein null
private String deviceToken; // sirf push ke liye — baaki mein null
}Problem: phoneNumber ek EmailNotification object mein bhi exist karta hai — as null.
Code null check karta rahega. Koi enforcement nahi.
sealed interface Notification
permits EmailNotification, SmsNotification, PushNotification {}
record EmailNotification(
String to,
String subject,
String body
) implements Notification {}
record SmsNotification(
String phoneNumber,
String message
) implements Notification {}
record PushNotification(
String deviceToken,
String title,
String body
) implements Notification {}phoneNumber sirf SmsNotification mein exist karta hai — kyunki wahi uska ghar hai.
void send(Notification n) {
switch (n) {
case EmailNotification e ->
emailService.send(e.to(), e.subject(), e.body());
case SmsNotification s ->
smsService.send(s.phoneNumber(), s.message());
case PushNotification p ->
pushService.send(p.deviceToken(), p.title(), p.body());
}
}Koi null nahi. Koi instanceof chain nahi.
Kal WhatsAppNotification add karo — compiler batayega ki send() mein handle karna hai.
Yeh question interviews mein directly aata hai: "Toh aap records kab use karenge aur kab nahi?"
| Dimension | DOP (Records + Sealed + Pattern Matching) | OOP (Traditional Classes) |
|---|---|---|
| Best fit | DTOs, API responses, event payloads, value objects, state machines | Business logic services, infrastructure classes, behavior-rich domain objects |
| Data | Immutable, transparent | Encapsulated, mutable as needed |
| Behavior | Separate — external functions/methods | Co-located with data |
| Null safety | Structural — type system se enforce | Manual — null checks required |
| Inheritance | Sealed hierarchy — controlled | Open — flexible |
| JPA Entities | ❌ Not suitable | ✅ Use traditional classes |
Rule of thumb:
- Agar class sirf data carry kar rahi hai → DOP
- Agar class kuch karta bhi hai → OOP
- Real applications mein dono saath chalte hain — yeh either/or nahi hai
January 2026 mein Brian Goetz ne OpenJDK pe ek major design note publish kiya: "Data-Oriented Programming for Java: Beyond Records"
Records ke saath ek "cliff" hai. Jaise hi thoda deviate karo — mutable field chahiye, internal representation API se different ho, ya inheritance chahiye — saare record benefits chale jaate hain. Tum wapas blank traditional class pe ho, sab manually likhna padta hai.
// ⚠️ EXPLORATORY SYNTAX ONLY
// Yeh Java mein abhi exist NAHI karta
// Koi JEP number nahi | Koi target version nahi | Pure design note hai
carrier class Money(long amount, Currency currency) {
component long amount;
component Currency currency;
// Internal representation API se different ho sakti hai
// Mutable fields allowed hain
// Inheritance possible hai
}Key idea: carrier class ek "almost record" hai. State description wahi, pattern matching wahi — lekin constraints relaxed hain.
| Item | Status |
|---|---|
| Design note published | ✅ January 26, 2026 — openjdk.org |
| Mailing list discussion | ✅ Active — last update February 25, 2026 |
| JEP number assigned | ❌ None |
| Target Java version | ❌ None |
| Preview status | ❌ None |
| Production-ready | ❌ Do not include in production planning |
Project Amber ka direction clear hai: DOP Java ka primary data modeling paradigm ban raha hai.
| Feature | Java Version | Status | Use Case |
|---|---|---|---|
| Records | Java 16 | ✅ Stable | DTOs, value objects, responses |
| Sealed Classes | Java 17 | ✅ Stable | Fixed variants, state machines |
Pattern Matching — instanceof |
Java 16 | ✅ Stable | Type-safe casting |
Pattern Matching — switch |
Java 21 | ✅ Stable | Exhaustive data processing |
| Record Patterns | Java 21 | ✅ Stable | Nested deconstruction |
| Carrier Classes | TBD | 🔬 Exploratory | — |
Step 1 — DTOs aur Value Objects ko Records mein convert karo
Agar koi class sirf data carry kar rahi hai —
UserDTO, ProductResponse, AddressVO — woh record ban sakti hai.
Exception: JPA entities nahi.
Step 2 — Status/State classes ko Sealed Interfaces mein shift karo
Jab tumhare paas fixed set of variants hain aur har variant ka alag data hoga — sealed interface + records perfect fit hai.
Step 3 — instanceof chains ko Pattern Matching se replace karo
// Purana — verbose aur unsafe cast
if (notification instanceof EmailNotification) {
EmailNotification e = (EmailNotification) notification;
emailService.send(e.getTo(), e.getSubject(), e.getBody());
}
// Naya — concise aur type-safe
if (notification instanceof EmailNotification e) {
emailService.send(e.to(), e.subject(), e.body());
}DOP especially important hai microservices aur distributed systems mein — jo 2026 mein har company ka default architecture hai.
Jab data ek service se doosri service mein jaata hai — REST response, Kafka event, gRPC message — woh naturally immutable aur transparent hota hai. DOP usi reality ko code mein accurately represent karta hai.
BellSoft ke 2024 Java Developer Survey ke according, Records 55% developer adoption pe hain — sabse popular modern Java feature. Interviewers expect karte hain ki final year students records aur pattern matching comfortable ho ke use karein.
Java ab sirf "everything is an object" nahi raha.
Records, Sealed Classes, Pattern Matching — yeh teen features milke data ko Java mein first-class citizen banate hain. Aur 2026 mein, Project Amber team Carrier Classes ke saath isko aur aage le jaane ki taiyari mein hai.
Toh agli baar jab tum ek UserDTO banana shuru karo —
ek second ruko aur poochho:
"Kya yeh ek record ho sakta hai?"
Chances hain — haan, ho sakta hai.
| Resource | Type | Start Karo Agar... |
|---|---|---|
| Baeldung: DOP in Java | Tutorial | Pehli baar DOP practically try karna hai |
| Inside Java Newscast #105 — Carrier Classes | Video | 2026 mein Java kahan ja raha hai jaanna hai |
| Manning: Data-Oriented Programming in Java — Chris Kiehl | Book | Deeply samajhna aur production mein apply karna hai |
| Brian Goetz — Original DOP Article, InfoQ June 2022 | Article | Concept ki origin aur philosophy samajhni hai |
| DOP v1.1 Introduction — inside.java, May 2024 | Article Series | Principles ek-ek karke formally padhne hain |
| Beyond Records Design Note — openjdk.org, Jan 2026 | Design Doc | Language design mein genuinely curious ho |
| Inside Java Podcast Ep. 47 — Carrier Classes | Podcast | Commute pe sunna chahte ho |
| Devoxx Belgium 2025 — The Three Amigos in Java | Talk | Visual, example-driven explanation prefer karte ho |
Content accurate as of April 7, 2026. Carrier Classes section: re-verify before sharing if more than 3 months have passed — active development area.