Java 𝗖𝗼𝗿𝗲 𝗝𝗮𝘃𝗮 → How do you sort a Map? → Implement a Singleton class. → Difference between Comparable and Comparator. → What are the new features introduced in Java 7 and 8? Key features of Java 8, 11, and 17. → What is try-with-resources? → What is a multi-catch block in Java? → Difference between Runnable and Callable. → Types of exceptions in Java and the exception hierarchy. → What are the different design patterns in Java? → Explain OOP principles. → Internals of ConcurrentHashMap. → How does Java Garbage Collection work? 𝗗𝗦𝗔/𝗖𝗼𝗱𝗶𝗻𝗴 → How to identify duplicate strings in a list? → Write a program to check if a string is a palindrome. → Combination Sum II (recursion-based problem). → Given an array, remove odd numbers, multiply remaining elements by a constant, and return the sum using Java Streams. → Find the missing number in a consecutive array. → Move all zeroes to the end of an array. → Check whether two strings are anagrams. → Find the longest common prefix among strings. → Longest Increasing Subsequence (LIS). → Best time to buy and sell stock (maximize profit). → Dijkstra’s Algorithm. → Coin Change problem (minimum coins). → Reverse-add palindrome problem. 𝗗𝗮𝘁𝗮𝗯𝗮𝘀𝗲 (𝗦𝗤𝗟) → How to retrieve the number of tables and their columns in a SQL database? → What is the purpose of database indexing? → How to detect duplicate records in SQL? → How would you design a schema for a ride-sharing application? 𝗪𝗲𝗯/𝗙𝗿𝗮𝗺𝗲𝘄𝗼𝗿𝗸𝘀 → Difference between REST and SOAP. → What is Spring Framework? → Why is Spring used? → Difference between Spring and Spring Boot. → How does dependency injection (autowiring) work in Spring? → What is Spring Security? → What is a RESTful API? → Difference between HTTP and HTTPS. 𝗦𝘆𝘀𝘁𝗲𝗺 𝗗𝗲𝘀𝗶𝗴𝗻 → Explain the architecture of a recent project you worked on. → Design a fraud detection system for transactions. → Database design for a ride-sharing platform. → Design a data warehouse for an e-commerce platform. → Design a news aggregation system. 𝗦𝗲𝗿𝘃𝗲𝗿/𝗦𝘆𝘀𝘁𝗲𝗺 → How to identify root causes of server crashes? → How to monitor server memory usage? → How to debug high CPU or memory utilization in JVM? → How to capture heap dumps and thread dumps? 𝗞𝗲𝗲𝗽𝗶𝗻𝗴 𝘁𝗵𝗶𝘀 𝗶𝗻 𝗺𝗶𝗻𝗱, 𝗜 𝘄𝗲𝗻𝘁 𝗱𝗲𝗲𝗽 𝗮𝗻𝗱 𝗱𝗼𝗰𝘂𝗺𝗲𝗻𝘁𝗲𝗱 𝗲𝘃𝗲𝗿𝘆𝘁𝗵𝗶𝗻𝗴 𝗶𝗻𝘁𝗼 𝗮 𝗝𝗮𝘃𝗮 𝗕𝗮𝗰𝗸𝗲𝗻𝗱 𝗗𝗲𝘃𝗲𝗹𝗼𝗽𝗲𝗿 𝗚𝘂𝗶𝗱𝗲. #java #backend
Java Development and Programming Tutorials and Best Practices
More Relevant Posts
-
🚀 Java Records: Features You Can Use (and Limits You Must Respect) By now, it’s clear that records are not just “shorter classes.” But here’s where things get interesting: Records are powerful — but only within a strict boundary Understanding both sides is what separates basic usage from real engineering clarity. 🧩 What records CAN do (yes, they’re more capable than you think) 🔹 1. Generics — fully supported Records work seamlessly with generics: public record Response<T>(T data, String status) {} 👉 Perfect for API wrappers, responses, and reusable models. 🔹 2. Methods — behavior is allowed Records aren’t “dumb containers.” public record User(Long id, String name) { public String displayName() { return name.toUpperCase(); } } ✔ You can add logic ✔ You can derive values But the state itself remains immutable. 🔹 3. Static members & blocks public record User(Long id, String name) { public static final String TYPE = "USER"; static { System.out.println("Record loaded"); } } ✔ Works just like normal classes ❗ But static ≠ instance state 🔹 4. Nested records (very useful) public record Order(Long id, Item item) { public record Item(String name, double price) {} } 👉 Clean way to model structured data 👉 Great for DTO hierarchies 🔹 5. Composition (record inside record) public record Order(Long id, Money price) {} public record Money(String currency, double amount) {} 👉 This is how you build real-world models 👉 Encourages clean, modular design 🔹 6. Validation annotations (Spring-friendly) public record User( @NotNull Long id, @NotBlank String name ) {} ✔ Works with Spring Boot ✔ Works with Hibernate Validator 👉 Records integrate cleanly with modern frameworks. ⚠️ What records CANNOT do (this is where people get it wrong) ❌ No extra instance fields You cannot add a hidden state: private int age; // ❌ not allowed 👉 All states must be declared in the record header. ❌ Cannot extend classes Records implicitly extend: java.lang.Record So: public record User(...) extends BaseEntity {} // ❌ not allowed ❌ No mutability — ever No setters No field updates No state changes 👉 Immutability is enforced, not optional. 🧠 The real design principle Records are built on: Structural immutability + value-based identity Not: “Flexible object with data + behavior” 🔥 Why this matters Because records push you toward: Clear data modeling Explicit contracts Safer APIs Fewer hidden bugs They remove: ❌ Accidental state ❌ Implicit behavior ❌ Uncontrolled changes 🧩 Final mental model Think of records as: A restricted Java class optimized for data modeling — not behavior modeling 💡 Clean takeaway Records support generics, methods, static members, nested types, and validation — but within a strictly controlled, immutable structure. #Java #JavaRecords #BackendDevelopment #SpringBoot #SystemDesign #SoftwareEngineering #JavaDeveloper #CleanCode #Programming #APIDesign
To view or add a comment, sign in
-
static in Java, Not Just a Keyword, It’s a Production Decision Learnings from fixing production Bugs..... Most developers learn static early… But very few understand how dangerous or powerful it becomes in real backend systems. Let’s break it down 👇 ⚡ What static really means When you mark something static, you’re saying: 👉 “This belongs to the class, not to individual objects” 👉 “This will be shared across all requests, threads, and users” In backend systems, that’s a big deal. Where static actually helps in production ✅ 1. Constants (Best Use Case) public static final String STATUS_ACTIVE = "ACTIVE"; ✔ No duplication ✔ Memory efficient ✔ Thread-safe ✅ 2. Utility Classes public class DateUtils { public static String format(Date date) { ... } } ✔ Stateless ✔ Reusable across services ✔ No object creation overhead ✅ 3. Caching (Careful Usage) public static Map<String, Config> cache = new HashMap<>(); ✔ Fast access ✔ Avoids repeated DB calls ⚠ But NOT thread-safe unless handled properly! Where static breaks production systems ❌ 1. Shared Mutable State (Biggest Mistake) public static int loginAttempts = 0; Imagine: 1000 users logging in simultaneously All threads updating the same variable 🔥 Result: Race conditions Wrong data Security issues ❌ 2. Memory Leaks Static objects live till JVM dies public static List<User> users = new ArrayList<>(); If this keeps growing → 💥 OutOfMemoryError ❌ 3. Breaking Framework Lifecycles Frameworks like Spring Boot, Hibernate manage objects (Beans) for you. If you use static: 👉 You go outside the container 👉 Lose dependency injection 👉 Lose lifecycle control ❌ 4. Testing Becomes Hard Static methods: Cannot be easily mocked Lead to tightly coupled code ⚖️ Golden Rules ✔ Use static for: Constants Stateless utilities ❌ Avoid static for: Business logic User/session data Mutable shared state 🧩 Real Production Insight Servlets are singleton by design. If you combine that with static state: 👉 You’re now sharing data across: All users All sessions All threads That’s how subtle production bugs are born. 🧠 Final Thought static is not about syntax… It’s about understanding memory, concurrency, and system design. Use it right → ⚡ High performance Use it wrong → 💣 Production incident If you’re building backend systems, mastering this one concept will save you from some of the hardest bugs you’ll ever debug. #Java #BackendEngineering #SystemDesign #Concurrency #SpringBoot
To view or add a comment, sign in
-
Day 28 — #100DaysOfJava ☕ Today a user typed something in a browser. My Java code received it, processed it, and sent a response back. That is client-server communication. And I built it from scratch. --- What I built today. A simple login form in HTML. User types username and password. Clicks submit. A Java Servlet receives that data on the server, reads it, and sends a response back to the browser. No framework. No Spring. No magic. Just raw Java talking directly to an HTTP request. --- How it actually works — and why every Spring Boot developer should understand this. The browser submits a form with method="post" to action="./firstServlet". The server sees that URL and maps it to my Servlet — because of this one annotation: @WebServlet("/firstServlet") That annotation replaced an entire XML configuration file. One line. Done. The Servlet extends HttpServlet and overrides two methods: doGet() — handles GET requests. When someone just visits the URL. doPost() — handles POST requests. When someone submits a form. Inside doPost(): String username = request.getParameter("username"); String password = request.getParameter("password"); PrintWriter writer = response.getWriter(); writer.print("Hello " + username); request.getParameter() reads the form field by its name attribute. PrintWriter writes the response back to the browser. That is the complete cycle. Request in. Process. Response out. --- What this taught me that no tutorial explains clearly. Every HTTP request has a method — GET or POST. GET is for fetching data. POST is for sending data. This is not just a Servlet concept. This is how the entire web works. Every form submission, every API call, every button click in a web app — underneath it is either a GET or a POST going to a server somewhere. Understanding this at the Servlet level means REST APIs, Spring Boot controllers, and API design all make immediate sense. @WebServlet maps a URL to a Java class. In Spring Boot, @RequestMapping and @GetMapping do the exact same thing — just with more features. Same concept. Different syntax. --- What Spring Boot does that raw Servlets do not. With raw Servlets — I write doGet() and doPost() manually. I configure the server. I handle everything. With Spring Boot — @RestController and @GetMapping handle all of this automatically. The Servlet container is embedded. Configuration is automatic. But here is the thing — Spring Boot is doing Servlet work underneath. It IS a Servlet application. Understanding the foundation means I will never be confused by what Spring Boot is doing for me. --- One thing I noticed in my own code today. I printed the password directly in the response: writer.print("I know your password " + password) Day 1 ... .......Day 28 To any developer reading this — what was the moment HTTP requests finally clicked for you? Drop it below. 👇 #Java #Servlets #HttpServlet #BackendDevelopment #WebDevelopment #100DaysOfJava #JavaDeveloper #LearningInPublic
To view or add a comment, sign in
-
Stop writing Java Switch statements like it’s 2004! If you are still writing switch statements with break; at the end of every line, you are living in the past! Java has transformed the humble switch from a clunky branching tool into a powerful, functional expression. Here is the evolution of how we control logic in Java: 1️⃣ The "Classic" Era (Java 1.0 - 6) * Syntax: case X: ... break; * Limitation: Only primitives (int, char) and Enums. * The Risk: "Fall-through" bugs. Forget one break and your logic cascades into chaos. 2️⃣ The "Modern Expression" (Java 14) Java 14 turned the Switch into an Expression. It can now return a value! * Arrow Syntax (->): No more break. It’s cleaner and safer. * Assignment: var result = switch(val) { ... }; * Yield: Use yield to return values from complex multi-line blocks. 3️⃣ The "Pattern Matching" Powerhouse (Java 21) This is the game changer. Switch is no longer just for values; it’s for Types. * Case Patterns: Switch directly on an Object. * Automatic Casting: No more instanceof followed by manual casting. * Guarded Patterns: Use the when keyword to add logic filters directly into the case. * Null Safety: Explicitly handle case null without crashing. Sample : /** * SCENARIO: Processing a result object that could be * a String, an Integer, or a custom Status record. */ // 🛑 THE OLD WAY (Java 8) - Verbose and manual public String handleResultOld(Object result) { if (result == null) { return "Unknown"; } if (result instanceof String) { String s = (String) result; // Manual casting return "Message: " + s; } else if (result instanceof Integer) { Integer i = (Integer) result; return "Code: " + i; } return "Unsupported"; } // ✅ THE MODERN WAY (Java 21) - Concise and Type-Safe public String handleResultModern(Object result) { return switch (result) { case null -> "Unknown"; case String s when s.isBlank() -> "Empty Message"; case String s -> "Message: " + s; // Automatic casting case Integer i -> "Code: " + i; default -> "Unsupported"; }; } #Java21 #ModernJava #BackendDevelopment #Coding #TechCommunity #Developers #LearningToCode
To view or add a comment, sign in
-
Mastering Java Streams: What’s Actually Happening Under the Hood? Ever wondered why Java Streams are called "Lazy"? Or why adding more intermediate operations doesn't necessarily slow down your code? The secret lies in the Internal Flow. Unlike traditional Collections, Streams don't process data step-by-step for the entire list. Instead, they use a Single-Pass Execution model. 🏗️ The 3 Stages of a Stream The Source: Where the data comes from (Lists, Sets, Arrays). Intermediate Operations: These are Lazy. Operations like .filter() or .map() don’t execute immediately. They just build a "recipe" or a pipeline of instructions. Terminal Operations: This is the Trigger. Operations like .collect(), .findFirst(), or .forEach() start the engine. Without this, nothing happens. 🧠 The "Pull" Mechanism Java Streams don't "push" every element through the entire pipeline one by one. Instead, the Terminal Operation "pulls" data from the source through the pipeline. Imagine a factory line: instead of moving every item to the next station, the worker at the very end of the line asks for one finished product. This triggers the previous stations to work only as much as needed to produce that one item. 💻 Code in Action: Lazy Evaluation & Short-Circuiting Check out this example. Even though we have a list of 1,000 items, the stream only processes what it needs. List<String> names = Arrays.asList("Java", "Spring", "Hibernate", "Microservices", "Docker"); String result = names.stream() .filter(s -> { System.out.println("Filtering: " + s); return s.length() > 4; }) .map(s -> { System.out.println("Mapping: " + s); return s.toUpperCase(); }) .findFirst() // Terminal Operation .get(); System.out.println("Result: " + result); What happens here? It checks "Java" (fails filter). It checks "Spring" (passes filter). It immediately maps "Spring" to "SPRING". findFirst() is satisfied, so it stops. It never even looks at "Hibernate" or "Docker"! 💡 Why does this matter for your LinkedIn reach? (and your code) Performance: Drastically reduces unnecessary computations. Memory Efficiency: Processes elements in a single pass rather than creating intermediate data structures. Readability: Clean, declarative code that describes what to do, not how to do it. Which do you prefer? The classic for-loop or the Stream API? Let's discuss in the comments! 👇 #Java #Programming #SoftwareDevelopment #Backend #JavaStreams #CleanCode #TechTips
To view or add a comment, sign in
-
-
🚀 Java Wrapper Classes: Hidden Behaviors That Trip Up Even Senior Developers Most developers know wrapper classes. Very few understand what happens under the hood — and that’s exactly where top companies separate candidates. Here’s a deep dive into the concepts that actually matter 1. Integer Caching Integer a = 4010; Integer b = 4010; System.out.println(a == b); // false Integer c = 127; Integer d = 127; System.out.println(c == d); // true Q.Why? Java caches Integer values in the range -128 to 127. Inside range → same object (cached) Outside range → new object (heap) 💡 Pro Insight: You can even extend this range using: -XX:AutoBoxCacheMax=<size> 2. == vs .equals() — Silent Bug Generator System.out.println(a == b); // false → reference comparison System.out.println(a.equals(b)); // true → value comparison Using == with wrapper objects is one of the most common production bugs. Rule: == → checks memory reference .equals() → checks actual value 3. hashCode() vs identityHashCode() System.out.println(a.hashCode()); System.out.println(System.identityHashCode(a)); Two objects can have: Same value → same hashCode() Different memory → different identityHashCode() 4. Silent Overflow in Primitive Conversion Integer a = 4010; byte k = a.byteValue(); // -86 What actually happens: byte range = -128 to 127 4010 % 256 = 170 170 interpreted as signed → -86 No error. No warning. This is how real-world bugs sneak into systems. 5. Powerful Utility Methods (Underrated) Integer.toBinaryString(4010); Integer.toHexString(4010); Integer.bitCount(4010); Integer.numberOfLeadingZeros(4010); Useful in: Bit manipulation Competitive programming Low-level optimization 6. Character & Boolean — Also Cached Boolean b1 = true; Boolean b2 = true; System.out.println(b1 == b2); // true Boolean → fully cached Character → cached in ASCII range 7. Character Utilities = Clean Code Character.isLetter('a'); Character.isDigit('3'); Character.isWhitespace('\t'); Character.toUpperCase('a'); The Big Picture Wrapper classes are NOT just primitives with methods. They reveal how Java handles: Memory optimization Object identity Autoboxing behavior Performance trade-offs A big thanks to my mentors Syed Zabi Ulla, peers, and the amazing developer community Oracle for continuously pushing me to go beyond basics and truly understand concepts at a deeper level. #Java #JVM #CoreJava #CodingInterview #FAANG #SoftwareEngineering #BackendDevelopment #ProgrammingTips
To view or add a comment, sign in
-
-
🚀 Understanding Generics in Java – Write Flexible & Type-Safe Code If you’ve ever worked with collections like List or Map, you’ve already used Generics — one of the most powerful features in Java. 🔹 What are Generics? Generics allow you to write classes, interfaces, and methods with a placeholder for the data type. This means you can reuse the same code for different data types while maintaining type safety. 🔹 Why use Generics? ✔️ Eliminates type casting ✔️ Provides compile-time type safety ✔️ Improves code reusability ✔️ Makes code cleaner and more readable 🔹 Simple Example: List<String> names = new ArrayList<>(); names.add("Sneha"); // names.add(10); ❌ Compile-time error 🔹 Generic Class Example: class Box<T> { private T value; public void set(T value) { this.value = value; } public T get() { return value; } } 🔹 🔥 Advanced Concepts Explained 🔸 1. Bounded Types (Restricting Types) You can limit what type can be passed: class NumberBox<T extends Number> { T value; } 👉 Only Integer, Double, etc. are allowed (not String) 🔸 2. Wildcards (?) – Flexibility in Collections ✔️ Unbounded Wildcard List<?> list; 👉 Can hold any type, but limited operations ✔️ Upper Bounded (? extends) List<? extends Number> list; 👉 Accepts Number and its subclasses 👉 Used when reading data ✔️ Lower Bounded (? super) List<? super Integer> list; 👉 Accepts Integer and its parent types 👉 Used when writing data 💡 Rule: PECS → Producer Extends, Consumer Super 🔸 3. Generic Methods public <T> void print(T data) { System.out.println(data); } 👉 Works independently of class-level generics 🔸 4. Type Erasure (Important for Interviews) Java removes generic type info at runtime: List<String> → List 👉 No runtime type checking 👉 Only compile-time safety 🔸 5. Multiple Bounds <T extends Number & Comparable<T>> 👉 A type must satisfy multiple conditions 🔸 6. Restrictions of Generics ❌ Cannot use primitives (int, double) → use wrappers ❌ Cannot create generic arrays ❌ Cannot use instanceof with generics 💡 Final Insight: Generics are not just a feature—they are a design tool that helps build scalable, reusable, and maintainable applications. Mastering advanced concepts like wildcards and type erasure can set you apart as a strong Java developer. #Java #Generics #AdvancedJava #Programming #JavaDeveloper #Coding #TechInterview
To view or add a comment, sign in
-
Every Java developer has confidently used these three terms. JVM. JDK. JRE. Most of them have no idea what the difference actually is. (Don't worry. Neither did I when I started.) Let's go back to the promise Java made in 1995 -> "Write Once, Run Anywhere." Sounds magical. But HOW? How does the same code run on Windows, Mac, and Linux without changing a single line? The answer is the JVM -> Java Virtual Machine. When you write Java code, it doesn't become machine code directly. It first becomes something called Bytecode. Bytecode is like a middle language not human readable, not machine readable either. It's in between. Now here's the trick. Every operating system has its own JVM installed. And the JVM's only job is to take that Bytecode and translate it into instructions YOUR machine understands. Windows JVM speaks Windows. Mac JVM speaks Mac. Linux JVM speaks Linux. But your code? Your code never changes. That's the magic. That's "Write Once, Run Anywhere." Okay. So where do JDK and JRE fit in? Think of it like a kitchen. JVM -> the stove. It runs and executes things. JRE (Java Runtime Environment) -> the full kitchen. The stove + everything needed to actually cook. Libraries, tools, the works. If you just want to RUN a Java program, JRE is enough. JDK (Java Development Kit) -> the kitchen PLUS a recipe book, knife set, and a chef's manual. Everything in JRE plus the tools to actually WRITE and BUILD Java programs. Compilers. Debuggers. The full package. So -> -> User who just runs your app? They need JRE. -> You, the developer building it? You need JDK. -> Under all of it, quietly doing the real work? JVM. Here's why this matters more than you think. Ever seen this error? "Java is not recognised as an internal or external command" That's your machine saying I have no idea what Java is. You never gave me a JRE or JDK. Understanding JVM, JDK, and JRE isn't just theory. It saves you hours of debugging confusion. If you read this far... This is Post #2 of my Java series -> the story behind the code. Next up: How Java actually compiles and runs your code step by step, from the line you write to the output on your screen. Follow SHABANA FATHIMA so you don't miss it. JVM, JDK, JRE did this finally click for you, or were you already a pro? 👇 #Java #JavaSeries #JVM #JDK #JRE #SoftwareEngineering #Programming #LearnToCode #BackendDevelopment #TechHistory
To view or add a comment, sign in
-
-
⚔️ Java Records vs Lombok (@Data) — Which One Should You Use? Short answer: ❌ Records are NOT “better” in general ✅ But they SHOULD be your default for DTOs The real difference isn’t syntax… it’s design philosophy. 🧠 What you’re actually comparing 🔵 Java Record public record UserDTO(Long id, String name) {} Immutable by design All fields required at creation No setters Value-based equality 👉 A data contract 🟢 Lombok @Data @Data public class UserDTO { private Long id; private String name; } Mutable Setters everywhere Flexible construction Hidden generated code 👉 A general-purpose object ⚖️ The real difference (not just boilerplate) This is where most developers get it wrong: Lombok → “write less code” Records → “write safer code” 🔥 The trade-off: Flexibility vs Correctness Lombok gives you freedom: ✔ Add fields anytime ✔ Mutate objects anywhere ✔ Use builders / no-arg constructors But also: ❌ Easy to break API contracts ❌ Hidden side effects ❌ Harder debugging Records enforce discipline: ✔ Immutable ✔ Fully initialized ✔ Predictable behavior ✔ Thread-safe by default But: ❌ No partial construction ❌ No mutation ❌ Less flexibility 🚨 Real-world bug example With Lombok: dto.setName("newName"); // can happen anywhere 👉 In large systems, this leads to: unexpected state changes hard-to-trace bugs With records: // no setter — mutation is impossible 👉 Entire class of bugs: gone 🧩 Where each one fits (this is the real answer) ✅ Use Records for: DTOs API responses Request objects JPA projections Read-only data 👉 Anything that represents a data snapshot ✅ Use Lombok / POJO for: JPA Entities (very important) Mutable domain objects Builder-heavy flows Legacy framework compatibility 👉 Anything that needs lifecycle + mutation ⚠️ Important mistake to avoid “Let’s replace all Lombok classes with records” ❌ Don’t do this Especially NOT for: @Entity public record User(...) {} // ❌ breaks JPA 🧠 Senior-level insight Lombok optimizes for developer speed Records optimize for system correctness 💡 Final mental model If your object represents data → Record If your object represents behavior → Class If your object needs mutation → Lombok / POJO 🚀 Final takeaway Records don’t replace Lombok They replace a specific misuse of Lombok — mutable DTOs If you’re still defaulting to @Data for DTOs, you’re solving yesterday’s problem with yesterday’s tool. #Java #JavaRecords #Lombok #SpringBoot #BackendDevelopment #SystemDesign #SoftwareEngineering #JavaDeveloper #CleanCode #Programming
To view or add a comment, sign in
-
Optional Misuse Patterns in Java: The Problem: A user lookup crashes in production with NoSuchElementException. The developer is confused — they used Optional, so it should be safe. But they called .get() directly without checking if the value is present. The Optional wrapper added zero safety. Root Cause: Optional was introduced in Java 8 to make absent values explicit and force callers to handle the empty case. But calling .get() on an empty Optional throws NoSuchElementException — just as calling a method on null throws NullPointe java User u = userRepo.findById(id).get(); That one line is no safer than a null dereference. Optional.get() on an empty Optional throws NoSuchElementException. Calling a method on null throws NullPointerException. Different exception, identical outcome. The Optional wrapper added zero protection. Optional was introduced to make absence explicit and force the caller to handle it. But calling .get() skips the entire contract. You have paid the ceremony tax with zero safety benefit. The other anti-pattern is isPresent() + get() — it works, but it is just a verbose null check. The same bug is still possible if someone removes the isPresent() guard later. Three correct patterns: java // 1 — fail with a meaningful exception (service layer default) .orElseThrow(() -> new UserNotFoundException(id)) // 2 — provide a safe default .orElse(User.anonymous()) // 3 — return Optional to caller, let them decide return userRepo.findById(id); Prevention Checklist: ->Never call Optional.get() without an explicit guard ->Prefer orElseThrow() at service layer — fail fast with meaningful exception ->Use orElseGet() instead of orElse() when the default is expensive to create ->Return Optional<T> from repo/service when absence is expected and valid ->Never use Optional as a method parameter or entity field — only as return type ->Enable IntelliJ inspection: "Optional.get() without isPresent()" Lesson: Optional.get() without a guard is just a different way to write a NPE. Optional forces you to think about the empty case — use its API to handle it. orElseThrow() for service layers. orElse() for defaults. Return Optional when absence is valid. Never call .get() directly. It is not a safe operation. #Java #DataStructures #DSA #SystemDesign #SpringBoot #BackendDevelopment #SoftwareEngineering #JavaDeveloper #Programming
To view or add a comment, sign in
-
More from this author
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