💡 Enums were too limited, inheritance was too open. So, Sealed Classes fixed both. 🔒 What are Sealed Classes? Sealed classes let you restrict which classes can extend or implement a class/interface. Instead of anyone extending your class, you explicitly allow only specific subclasses. ✅ Why this matters? • Better domain modeling (especially in DDD) • Exhaustive pattern matching (no missing cases in switch) • More secure APIs (no unintended subclassing) • Cleaner architecture boundaries 🧠 Example: public sealed class Payment permits UpiPayment, CardPayment {} public final class UpiPayment extends Payment {} public final class CardPayment extends Payment {} ————————————————————————— No random developer can extend Payment. Java compiler enforces your design rules. 💡 Think of Sealed Classes as: Enums + Inheritance + Compile-time safety Java is evolving fast, Sealed Classes are a big step towards safer and more expressive APIs. Are you using Sealed Classes in production yet? 👇 #Java #Java17 #SealedClasses #BackendDevelopment #Microservices #SystemDesign #Programming
Java Sealed Classes: Restricting Inheritance and Improving Domain Modeling
More Relevant Posts
-
💡 𝗝𝗮𝘃𝗮/𝐒𝐩𝐫𝐢𝐧𝐠 𝐁𝐨𝐨𝐭 𝗧𝗶𝗽 - 𝗦𝘄𝗶𝘁𝗰𝗵 𝗘𝘅𝗽𝗿𝗲𝘀𝘀𝗶𝗼𝗻 💎 🕯 𝗧𝗿𝗮𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝗦𝘄𝗶𝘁𝗰𝗵 𝗦𝘁𝗮𝘁𝗲𝗺𝗲𝗻𝘁 The traditional switch statement has been part of Java since the beginning. It requires explicit break statements to prevent fall-through, which can lead to bugs if forgotten. Each case must contain statements that execute sequentially, making the code verbose and error-prone. 💡 𝗠𝗼𝗱𝗲𝗿𝗻 𝗦𝘄𝗶𝘁𝗰𝗵 𝗘𝘅𝗽𝗿𝗲𝘀𝘀𝗶𝗼𝗻 Switch expressions were introduced in Java 14 as a more concise and safe alternative. Using the -> syntax, you eliminate the need for break statements and can directly return values. Multiple cases can be grouped with commas, and the compiler enforces exhaustiveness for better safety. ✅ 𝗞𝗲𝘆 𝗕𝗲𝗻𝗲𝗳𝗶𝘁𝘀 ◾ No break statements, safer and cleaner code. ◾ Direct value assignment, treat switch as an expression. ◾ Multiple labels with comma separation. ◾ Compiler exhaustiveness checks, fewer runtime errors. 🤔 Which one do you prefer? #java #springboot #programming #softwareengineering #softwaredevelopment
To view or add a comment, sign in
-
-
🧵 Mastering Thread Lifecycle & State Transitions in Java 🚀 Understanding thread states is crucial for writing efficient, bug-free concurrent applications. Here's a quick breakdown: 6 Thread States in Java: 1️⃣ NEW – Thread created but not started 2️⃣ RUNNABLE – Executing or ready to execute 3️⃣ BLOCKED – Waiting for monitor lock 4️⃣ WAITING – Waiting indefinitely for another thread 5️⃣ TIMED_WAITING – Waiting for a specified time 6️⃣ TERMINATED – Execution completed Key Transitions: • start() → NEW → RUNNABLE • sleep()/wait(timeout) → RUNNABLE → TIMED_WAITING • wait() → RUNNABLE → WAITING • I/O or lock acquisition → RUNNABLE → BLOCKED • notify()/notifyAll() → WAITING → RUNNABLE Q1: What's the difference between BLOCKED and WAITING states? A: BLOCKED occurs when a thread is waiting to acquire a monitor lock. WAITING happens when a thread waits indefinitely for another thread to perform a specific action (like notify() or join()). BLOCKED is lock-specific, WAITING is action-specific. Q2: Can a thread transition directly from WAITING to RUNNABLE without entering BLOCKED? A: Yes! When notify()/notifyAll() is called, the waiting thread moves directly to RUNNABLE state. It only enters BLOCKED if it needs to reacquire a lock that's held by another thread. Q3: How does yield() affect thread state? A: yield() is a hint to the scheduler that current thread is willing to pause its execution. The thread remains in RUNNABLE state and may immediately resume running—no state change occurs. It's just a suggestion, not guaranteed behavior. 💡 Pro Tip: Use jstack or visualvm to monitor thread states in production applications—invaluable for debugging deadlocks and performance issues! What threading challenges have you faced recently? 👇 #Java #Multithreading #Concurrency #Programming #SoftwareEngineering
To view or add a comment, sign in
-
As projects grow, chaos grows with them. That’s why Java introduced 𝗽𝗮𝗰𝗸𝗮𝗴𝗲𝘀. Packages are not just folders. They are 𝗻𝗮𝗺𝗲𝘀𝗽𝗮𝗰𝗲𝘀. When you write: 𝐩𝐚𝐜𝐤𝐚𝐠𝐞 𝐜𝐨𝐦.𝐦𝐲𝐚𝐩𝐩.𝐦𝐨𝐝𝐞𝐥𝐬; You’re doing more than organizing files. You’re: • Preventing class name conflicts • Creating logical boundaries • Defining architectural layers Without packages: Two different developers could create a class named User and everything would collide. With packages: 𝐜𝐨𝐦.𝐦𝐲𝐚𝐩𝐩.𝐚𝐮𝐭𝐡.𝐔𝐬𝐞𝐫 and 𝐜𝐨𝐦.𝐦𝐲𝐚𝐩𝐩.𝐦𝐨𝐝𝐞𝐥𝐬.𝐔𝐬𝐞𝐫 can peacefully coexist. Packages also work closely with access modifiers: • public • private • protected • default (package-private) This creates controlled visibility. Today was about: • Why packages matter in real-world projects • How namespaces prevent conflicts • Structuring code for scalability Good developers don’t just write classes. They design structure. #Java #Packages #SoftwareArchitecture #CleanCode #Programming #LearningInPublic
To view or add a comment, sign in
-
-
Imagine this situation. You and your friend are working on a 𝐬𝐡𝐚𝐫𝐞𝐝 𝐰𝐡𝐢𝐭𝐞𝐛𝐨𝐚𝐫𝐝. You write a number on the board. Your friend reads it. Simple, right? But now imagine both of you are working 𝐢𝐧 𝐝𝐢𝐟𝐟𝐞𝐫𝐞𝐧𝐭 𝐫𝐨𝐨𝐦𝐬 with 𝐲𝐨𝐮𝐫 𝐨𝐰𝐧 𝐜𝐨𝐩𝐢𝐞𝐬 𝐨𝐟 𝐭𝐡𝐞 𝐛𝐨𝐚𝐫𝐝. You update your board. But your friend still sees the 𝐨𝐥𝐝 𝐯𝐚𝐥𝐮𝐞. This is exactly what can happen in 𝗺𝘂𝗹𝘁𝗶𝘁𝗵𝗿𝗲𝗮𝗱𝗲𝗱 𝗝𝗮𝘃𝗮 𝗽𝗿𝗼𝗴𝗿𝗮𝗺𝘀. Each thread may work with its 𝐨𝐰𝐧 𝐜𝐚𝐜𝐡𝐞𝐝 𝐜𝐨𝐩𝐲 𝐨𝐟 𝐯𝐚𝐫𝐢𝐚𝐛𝐥𝐞𝐬 instead of the shared memory. And that’s where the 𝗝𝗮𝘃𝗮 𝗠𝗲𝗺𝗼𝗿𝘆 𝗠𝗼𝗱𝗲𝗹 (𝗝𝗠𝗠) comes in. What is the Java Memory Model? The 𝗝𝗮𝘃𝗮 𝗠𝗲𝗺𝗼𝗿𝘆 𝗠𝗼𝗱𝗲𝗹 defines how: • Threads interact with memory • Changes made by one thread become visible to others • The JVM handles caching and reordering Without rules like this, concurrent programs would behave unpredictably. 𝐓𝐡𝐞 𝐕𝐢𝐬𝐢𝐛𝐢𝐥𝐢𝐭𝐲 𝐏𝐫𝐨𝐛𝐥𝐞𝐦 Example: class FlagExample { static boolean running = true; public static void main(String[] args) { new Thread(() -> { while (running) { // waiting } System.out.println("Thread stopped"); }).start(); running = false; } } You might expect the thread to stop immediately. But sometimes 𝗶𝘁 𝗸𝗲𝗲𝗽𝘀 𝗿𝘂𝗻𝗻𝗶𝗻𝗴 𝗳𝗼𝗿𝗲𝘃𝗲𝗿. Why? Because the thread may keep reading a 𝗰𝗮𝗰𝗵𝗲𝗱 𝘃𝗮𝗹𝘂𝗲 𝗼𝗳 𝗿𝘂𝗻𝗻𝗶𝗻𝗴. It never sees the update. The Fix → 𝐯𝐨𝐥𝐚𝐭𝐢𝐥𝐞 volatile static boolean running = true; Now Java guarantees: • Updates are visible to all threads • Threads read the latest value from memory 𝐯𝐨𝐥𝐚𝐭𝐢𝐥𝐞 ensures 𝘃𝗶𝘀𝗶𝗯𝗶𝗹𝗶𝘁𝘆, not locking. 𝐊𝐞𝐲 𝐈𝐝𝐞𝐚 Multithreading problems are not always about race conditions. Sometimes the issue is simply: • Threads not seeing the same data. Today was about understanding: • Why threads may see 𝗱𝗶𝗳𝗳𝗲𝗿𝗲𝗻𝘁 𝘃𝗮𝗹𝘂𝗲𝘀 • What the 𝗝𝗮𝘃𝗮 𝗠𝗲𝗺𝗼𝗿𝘆 𝗠𝗼𝗱𝗲𝗹 controls • How 𝐯𝐨𝐥𝐚𝐭𝐢𝐥𝐞 ensures 𝘃𝗶𝘀𝗶𝗯𝗶𝗹𝗶𝘁𝘆 Concurrency is not only about 𝗿𝘂𝗻𝗻𝗶𝗻𝗴 𝘁𝗵𝗶𝗻𝗴𝘀 𝗳𝗮𝘀𝘁𝗲𝗿. It’s also about 𝗺𝗮𝗸𝗶𝗻𝗴 𝘀𝘂𝗿𝗲 𝗲𝘃𝗲𝗿𝘆 𝘁𝗵𝗿𝗲𝗮𝗱 𝘀𝗲𝗲𝘀 𝘁𝗵𝗲 𝘀𝗮𝗺𝗲 𝗿𝗲𝗮𝗹𝗶𝘁𝘆. #Java #JavaConcurrency #JavaMemoryModel #Multithreading #SoftwareEngineering #LearningInPublic #Programming
To view or add a comment, sign in
-
-
🚀 Day 31 of Importance of Static block, Static variables and Static methods Today, I explored one of the most important concepts in Java – Static Keyword 🔥 🔹 Static Variables Belong to the class, not to objects. Only one copy is created and shared among all instances. Memory is allocated only once when the class is loaded. Accessed using the class name. 🔹 Static Methods Belong to the class rather than an object. Can be called without creating an object. Mostly used for utility methods. Cannot directly access non-static instance variables. 🔹 Static Block Executes when the class is loaded into memory. Used to initialize static variables. Runs before constructors. Executes only once. Static members are shared resources of a class. They improve memory efficiency and are perfect for common data or utility logic. Understanding how static works also helped me visualize JVM memory concepts like Class Area, Stack, and Heap. #Day31 #Java #LearningJourney #StaticKeyword #Programming #BackendDevelopment
To view or add a comment, sign in
-
-
Why Java isn't just "Write Once, Run Anywhere"—It’s "Check Once, Execute Twice." Most developers know that Java has a Compile-time and a Runtime. But internally, the "Brain" of Java switches focus during these two phases. 🚀 The Core Difference: Compile-time (The Architect): Works strictly on the Reference Type. Runtime (The Builder): Works strictly on the Actual Object Type. Let’s break down the internals: 🔹 Compile-time (The Static Phase): The Compiler (javac) is like a strict security guard. It only looks at the "Label" (Reference Type). If you have Animal myDog = new Dog();, the compiler only sees Animal. It checks if the method you are calling exists in the Animal class. It doesn't care what is actually sitting in memory yet. 🔹 Runtime (The Dynamic Phase): The JVM (Java Virtual Machine) is the executor. It looks at the actual memory heap. It sees the new Dog() object. When you call makeSound(), the JVM uses Dynamic Method Dispatch to look up the method in the Dog class, even if the reference was Animal. Key Takeaway: If your code doesn't pass the "Reference Check" at compile-time, it will never get to the "Object Execution" at runtime. #Java #Programming #Backend #SoftwareEngineering #JVM #CodingTips
To view or add a comment, sign in
-
-
I used to think equals() and == in Java were basically the same. They’re not. == checks if two references point to the same memory location. equals() checks if two objects are logically equal. That difference looks small. Until your HashMap stops working properly. In Java, if you override equals(), you must also override hashCode(). Because collections like HashMap use hashCode() first to find the bucket, and then equals() to confirm the match. Forget one of them… and your object becomes “invisible” inside the map. One small contract. One big lesson. #Java #BackendDevelopment #SoftwareEngineering #Programming
To view or add a comment, sign in
-
𝐖𝐡𝐲 𝐉𝐚𝐯𝐚 8 𝐢𝐬 𝐭𝐡𝐞 "𝐅𝐢𝐞𝐥𝐝 𝐇𝐨𝐬𝐩𝐢𝐭𝐚𝐥" 𝐟𝐨𝐫 𝐋𝐞𝐠𝐚𝐜𝐲 𝐂𝐨𝐝𝐞 🏥 I recently spent a month rescuing a 20-year-old "Big Ball of Mud" written in Java 1.5. My first lesson? Don't try to be a hero and jump straight to Java 21. When dealing with "Software Archaeology," you need a 𝐆𝐨𝐥𝐝𝐞𝐧 𝐁𝐫𝐢𝐝𝐠𝐞. ➤ 𝐓𝐡𝐞 𝐈𝐧𝐭𝐞𝐫𝐬𝐞𝐜𝐭𝐢𝐨𝐧 𝐨𝐟 𝐂𝐨𝐦𝐩𝐚𝐭𝐢𝐛𝐢𝐥𝐢𝐭𝐲 Java 8 is the last version that reliably compiles ancient Java 1.5 code while still running natively on modern ARM64 (Apple Silicon) hardware. It understands the past but lives in the present. ➤ 𝐓𝐨𝐨𝐥𝐢𝐧𝐠 𝐚𝐬 𝐚 𝐒𝐭𝐫𝐚𝐧𝐠𝐥𝐞𝐫 𝐅𝐢𝐠 By targeting Java 8, you can wrap old Ant builds in modern Gradle 7.6 wrappers. This allows you to modernize your CI/CD pipeline without changing a single line of business logic yet. ➤ 𝐒𝐭𝐚𝐛𝐢𝐥𝐢𝐳𝐞 𝐅𝐢𝐫𝐬𝐭, 𝐌𝐨𝐝𝐞𝐫𝐧𝐢𝐳𝐞 𝐒𝐞𝐜𝐨𝐧𝐝 Use Java 8 to fix your infrastructure (Docker) and your tests. Only once you have a "Green Build" on modern hardware should you attempt to move to Java 17 or 21. In refactoring, the fastest way forward is often a calculated step back to a stable baseline. Full article: https://lnkd.in/e6udWnaB 𝑯𝒆𝒍𝒑𝒇𝒖𝒍 𝑹𝒆𝒔𝒐𝒖𝒓𝒄𝒆𝒔 - 𝘖𝘳𝘢𝘤𝘭𝘦 𝘑𝘢𝘷𝘢 𝘚𝘌 𝘚𝘶𝘱𝘱𝘰𝘳𝘵 𝘙𝘰𝘢𝘥𝘮𝘢𝘱 https://lnkd.in/eebFfMVs - 𝘎𝘳𝘢𝘥𝘭𝘦 𝘛𝘰𝘰𝘭𝘤𝘩𝘢𝘪𝘯 𝘋𝘰𝘤𝘶𝘮𝘦𝘯𝘵𝘢𝘵𝘪𝘰𝘯 https://lnkd.in/eJb2mHUj - 𝘛𝘩𝘦 𝘚𝘵𝘳𝘢𝘯𝘨𝘭𝘦𝘳 𝘍𝘪𝘨 𝘗𝘢𝘵𝘵𝘦𝘳𝘯 𝘣y Martin Fowler https://lnkd.in/ecPh-Kzy #Java #LegacyCode #SoftwareArchitecture #Refactoring #Modernization #Programming
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development