├── Collections ├── java-collections-comparison-bw-objs.md ├── java-collections-introduction.md └── java-hashmap-documentation.md ├── core-java-programs ├── java-array-programs-guide.md ├── java-number-programs.md └── java-string-programs.md ├── core-java ├── core-java-notes.md ├── generics.md ├── interview-questions-answers-freshers-1.md ├── interview-questions-answers-freshers-2.md.md ├── interview-questions-zero-to-hero.md ├── notes-on-enum.md ├── notes-on-oops-concepts.md └── spring-boot-notes.md ├── exception-handling ├── interview-questions.md ├── notes-1.md ├── notes-2.md ├── notes-3.md └── notes-4-varous-exceptions.md ├── executor-service ├── AtomicReferference.md ├── ruf.txt ├── scenario-0.md ├── scenario-1.md └── scenario-2.md ├── file I O └── wkg-with-file-IO.md ├── java-8 ├── built-in-functional-Interfaces.md ├── functional-interface.md ├── java-8-programming-questions.md ├── lambda-ex.md ├── lambda-expressions.md ├── method-references.md ├── optional-class.md ├── streams-example-employee-sample.md └── streams-introduction.md └── multi-threading ├── multithreading-comprehensive-notes.md └── multithreading-simplified-notes.md /core-java/generics.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Example: Simple Generic Functional Interface 4 | 5 | ```java 6 | @FunctionalInterface 7 | interface I { 8 | T m1(T x); 9 | } 10 | 11 | public class Main { 12 | public static void main(String[] args) { 13 | // Using the generic interface with Integer type 14 | I obj1 = (x) -> { 15 | System.out.println("Lambda-Integer: " + x); 16 | return x; 17 | }; 18 | System.out.println(obj1.m1(999)); 19 | /* 20 | Output: 21 | Lambda-Integer: 999 22 | 999 23 | */ 24 | 25 | // Using the same interface with String type 26 | I obj2 = (String x) -> { 27 | System.out.println("Lambda-String: " + x); 28 | return "Hello " + x; 29 | }; 30 | System.out.println(obj2.m1("world")); 31 | /* 32 | Output: 33 | Lambda-String: world 34 | Hello world 35 | */ 36 | } 37 | } 38 | ``` 39 | 40 | ### Example: Generic Class with Type Parameter 41 | 42 | ```java 43 | public class Box { 44 | private T data; 45 | 46 | public void setData(T data) { 47 | this.data = data; 48 | } 49 | 50 | public T getData() { 51 | return data; 52 | } 53 | } 54 | 55 | public class Main { 56 | public static void main(String[] args) { 57 | // Using the generic Box with Integer type 58 | Box obj = new Box<>(); 59 | obj.setData(19); 60 | System.out.println(obj.getData()); // Output: 19 61 | 62 | // Using the same Box class with String type 63 | Box strBox = new Box<>(); 64 | strBox.setData("Hello Generic"); 65 | System.out.println(strBox.getData()); // Output: Hello Generic 66 | } 67 | } 68 | ``` 69 | 70 | [Back to Top](#table-of-contents) 71 | 72 | 73 | ## Generic Functional Interfaces 74 | 75 | Generic functional interfaces allow for type-safe operations with different data types while maintaining the single abstract method constraint. 76 | 77 | ### Key Characteristics: 78 | 79 | * Work with different data types 80 | * Enforce type safety at compile time 81 | * Improve code reusability 82 | * Enhance readability 83 | * Allow specifying types at instantiation 84 | 85 | [Back to Top](#table-of-contents) 86 | -------------------------------------------------------------------------------- /core-java/interview-questions-answers-freshers-2.md.md: -------------------------------------------------------------------------------- 1 | ## Java Concepts - Questions & Answers 2 | 3 | ## Main Method Concepts 4 | 5 | **1. Why is the main method static in Java?** 6 | The main method is static because the JVM needs to call it without creating an instance of the class. Static methods belong to the class itself, not to any object. 7 | 8 | **2. Can we run main() without the static keyword?** 9 | No, the JVM specifically looks for `public static void main(String[] args)`. Without static, you'll get a runtime error. 10 | 11 | **3. What if we write static public void instead of public static void?** 12 | Both are valid. The order of access modifiers and static keyword doesn't matter in Java. `static public void main` works the same as `public static void main`. 13 | 14 | **4. Can you declare the main method as final or private?** 15 | - **Final**: Yes, but it's unnecessary since main isn't typically overridden 16 | - **Private**: No, the JVM requires main to be public to access it 17 | 18 | ## Class Execution 19 | 20 | **5. Can we run a Java class without a main method?** 21 | - In standalone applications: No, you need main method to start execution 22 | - In web applications or when called by other classes: Yes, other methods can be invoked 23 | 24 | **6. Can you declare a class as final?** 25 | Yes, final classes cannot be extended (inherited). Examples: String, Integer, all wrapper classes. 26 | 27 | ## Static vs Non-Static 28 | 29 | **7. Can a static method reference a non-static variable?** 30 | No, static methods cannot directly access non-static (instance) variables because static methods belong to the class, while instance variables belong to specific objects. You'll get a compilation error. 31 | 32 | **8. Can we override static variables?** 33 | No, static variables cannot be overridden. They can be hidden in subclasses, but this is called "variable hiding," not overriding. Each class has its own copy of static variables. 34 | 35 | ## Keywords and Identifiers 36 | 37 | **9. Is 'main' a keyword in Java? What are other identifiers?** 38 | No, 'main' is not a keyword - it's an identifier (method name). 39 | 40 | **Java Keywords include**: class, public, static, void, if, else, for, while, int, boolean, final, abstract, extends, implements, try, catch, etc. 41 | 42 | **Identifiers are**: names given to variables, methods, classes, packages (like main, System, println, etc.) -------------------------------------------------------------------------------- /core-java/interview-questions-zero-to-hero.md: -------------------------------------------------------------------------------- 1 | # Java Interview Questions Repository 2 | 3 | This document contains a curated list of Java interview questions covering various topics from basic concepts to advanced features. 4 | 5 | ## Table of Contents 6 | 7 | | # | Question | 8 | | --- | ------------------------------------------------------------------------------------------------------- | 9 | | 1 | [Why is Java not 100% object-oriented?](#why-is-java-not-100-object-oriented) | 10 | | | **Java Basics** | 11 | | 2 | [What are the features of Java?](#what-are-the-features-of-java) | 12 | | 3 | [What do you mean by platform independence?](#what-do-you-mean-by-platform-independence) | 13 | | 4 | [What is the difference between JDK, JRE, and JVM?](#what-is-the-difference-between-jdk-jre-and-jvm) | 14 | | 5 | [What are the jobs of JVM?](#what-are-the-jobs-of-jvm) | 15 | | 6 | [What are the memory areas available in Java?](#what-are-the-memory-areas-available-in-java) | 16 | | 7 | [What is garbage collection in Java? What methods are related to GC?](#what-is-garbage-collection-in-java-what-methods-are-related-to-gc) | 17 | | 8 | [What is a package in Java?](#what-is-a-package-in-java) | 18 | | 9 | [What are the different data types in Java?](#what-are-the-different-data-types-in-java) | 19 | | 10 | [What are string literals?](#what-are-string-literals) | 20 | | 11 | [What is the difference between declaring, defining, and initializing a value?](#what-is-the-difference-between-declaring-defining-and-initializing-a-value) | 21 | | 12 | [What is the difference between a compiler, an interpreter, and bytecode?](#what-is-the-difference-between-a-compiler-an-interpreter-and-bytecode) | 22 | | 13 | [How many different ways are there to take input in Java?](#how-many-different-ways-are-there-to-take-input-in-java) | 23 | | 14 | [Can I import the same package/class twice? Will the JVM load the package twice at runtime?](#can-i-import-the-same-packageclass-twice-will-the-jvm-load-the-package-twice-at-runtime) | 24 | | | **Unicode and Identifiers** | 25 | | 15 | [What is Unicode, and which Unicode system does Java use?](#what-is-unicode-and-which-unicode-system-does-java-use) | 26 | | 16 | [Which non-Unicode characters can be used as the first character of an identifier?](#which-non-unicode-characters-can-be-used-as-the-first-character-of-an-identifier) | 27 | | | **Primitive Types and Wrapper Classes** | 28 | | 17 | [What are primitive types and their wrapper classes in Java?](#what-are-primitive-types-and-their-wrapper-classes-in-java) | 29 | | 18 | [What methods are inside primitive and wrapper classes?](#what-methods-are-inside-primitive-and-wrapper-classes) | 30 | | 19 | [What is autoboxing and unboxing?](#what-is-autoboxing-and-unboxing) | 31 | | | **Casting and Cloning** | 32 | | 20 | [What is casting (implicit and explicit)?](#what-is-casting-implicit-and-explicit) | 33 | | 21 | [Different types of cloning available in Java? Difference between deep cloning and shallow cloning?](#different-types-of-cloning-available-in-java-difference-between-deep-cloning-and-shallow-cloning) | 34 | | | **Strings and String Pool** | 35 | | 22 | [Why is String not mutable, and how to develop a mutable String in Java?](#why-is-string-not-mutable-and-how-to-develop-a-mutable-string-in-java) | 36 | | 23 | [What is the difference between String, StringBuilder, and StringBuffer?](#what-is-the-difference-between-string-stringbuilder-and-stringbuffer) | 37 | | 24 | [What is the String constant pool?](#what-is-the-string-constant-pool) | 38 | | 25 | [String s_1 = "anil"; vs. String s_2 = new String("anil");](#string-s_1--anil-vs-string-s_2--new-stringanil) | 39 | | | **Operators and Comparisons** | 40 | | 26 | [What is the difference between == and .equals?](#what-is-the-difference-between--and-equals) | 41 | | 27 | [How do you convert a String to an int (parse)?](#how-do-you-convert-a-string-to-an-int-parse) | 42 | | | **Singleton and Static** | 43 | | 28 | [What is a singleton class in Java?](#what-is-a-singleton-class-in-java) | 44 | | 29 | [What is static in Java?](#what-is-static-in-java) | 45 | | 30 | [Why is the main method static in Java?](#why-is-the-main-method-static-in-java) | 46 | | 31 | [Can we run main() without the static keyword?](#can-we-run-main-without-the-static-keyword) | 47 | | 32 | [Can we run a Java class without a main method?](#can-we-run-a-java-class-without-a-main-method) | 48 | | 33 | [Can you declare the main method as final or private?](#can-you-declare-the-main-method-as-final-or-private) | 49 | | 34 | [Does 'main' a keyword in Java? What are other identifiers?](#does-main-a-keyword-in-java-what-are-other-identifiers) | 50 | | 35 | [What if we write static public void instead of public static void?](#what-if-we-write-static-public-void-instead-of-public-static-void) | 51 | | 36 | [Can a static reference a non-static variable? What happens if it does?](#can-a-static-reference-a-non-static-variable-what-happens-if-it-does) | 52 | | 37 | [Can we override static variables?](#can-we-override-static-variables) | 53 | | 38 | [Can you declare a class as final?](#can-you-declare-a-class-as-final) | 54 | | | **Constructors** | 55 | | 39 | [What is a constructor? Give an example.](#what-is-a-constructor-give-an-example) | 56 | | 40 | [What is the main purpose of a constructor?](#what-is-the-main-purpose-of-a-constructor) | 57 | | 41 | [When is a constructor invoked?](#when-is-a-constructor-invoked) | 58 | | 42 | [What is a default constructor?](#what-is-a-default-constructor) | 59 | | 43 | [Can a constructor return any value?](#can-a-constructor-return-any-value) | 60 | | 44 | [What is constructor overloading? (multiple constructors)](#what-is-constructor-overloading-multiple-constructors) | 61 | | 45 | [What is the difference between a constructor and a method?](#what-is-the-difference-between-a-constructor-and-a-method) | 62 | | 46 | [What is constructor chaining?](#what-is-constructor-chaining) | 63 | | 47 | [What is a copy constructor?](#what-is-a-copy-constructor) | 64 | | 48 | [What is a destructor?](#what-is-a-destructor) | 65 | | 49 | [Can we declare a constructor as private or final?](#can-we-declare-a-constructor-as-private-or-final) | 66 | | 50 | [What are the this and super keywords? How are they used in constructors?](#what-are-the-this-and-super-keywords-how-are-they-used-in-constructors) | 67 | | 51 | [Can we call a subclass constructor from a superclass constructor?](#can-we-call-a-subclass-constructor-from-a-superclass-constructor) | 68 | | 52 | [Is it possible to inherit a constructor?](#is-it-possible-to-inherit-a-constructor) | 69 | | 53 | [Is it possible to invoke a constructor of a class more than once for an object?](#is-it-possible-to-invoke-a-constructor-of-a-class-more-than-once-for-an-object) | 70 | | | **Final Keyword** | 71 | | 54 | [What is the final keyword, and where can we use it?](#what-is-the-final-keyword-and-where-can-we-use-it) | 72 | | 55 | [What is the difference between the final method and an abstract method?](#what-is-the-difference-between-the-final-method-and-an-abstract-method) | 73 | | 56 | [Can we declare an interface as final?](#can-we-declare-an-interface-as-final) | 74 | | | **Overloading and Overriding** | 75 | | 57 | [What is the difference between method overloading and overriding?](#what-is-the-difference-between-method-overloading-and-overriding) | 76 | | 58 | [What are the rules associated with overloading and overriding?](#what-are-the-rules-associated-with-overloading-and-overriding) | 77 | | 59 | [Can we change the scope of the overridden method in the subclass?](#can-we-change-the-scope-of-the-overridden-method-in-the-subclass) | 78 | | 60 | [What is the covariant return type?](#what-is-the-covariant-return-type) | 79 | | 61 | [Can we override private methods? | static methods](#can-we-override-private-methods--static-methods) | 80 | | | **Access Modifiers and Visibility** | 81 | | 62 | [What are visibility modifiers and access modifiers? What are the scopes associated with them?](#what-are-visibility-modifiers-and-access-modifiers-what-are-the-scopes-associated-with-them) | 82 | | 63 | [What is the access modifier scope order (lower to higher)? What is default? Diff bw protected & default?](#what-is-the-access-modifier-scope-order-lower-to-higher-what-is-default-diff-bw-protected--default) | 83 | | 64 | [Can a constructor be declared as private? Why is it needed?](#can-a-constructor-be-declared-as-private-why-is-it-needed) | 84 | | 65 | [Can a protected method be accessed outside the package? If yes, how?](#can-a-protected-method-be-accessed-outside-the-package-if-yes-how) | 85 | | 66 | [Can a class be declared as private or protected? Why or why not?](#can-a-class-be-declared-as-private-or-protected-why-or-why-not) | 86 | | 67 | [How can we restrict subclassing in Java?](#how-can-we-restrict-subclassing-in-java) | 87 | | 68 | [Can an abstract method be private? Why or why not?](#can-an-abstract-method-be-private-why-or-why-not) | 88 | | | **Abstract Classes** | 89 | | 69 | [Can an abstract class have a constructor?](#can-an-abstract-class-have-a-constructor) | 90 | | 70 | [How do you create an abstract class?](#how-do-you-create-an-abstract-class) | 91 | | 71 | [Is at least one abstract method mandatory in an abstract class? (Concrete methods)](#is-at-least-one-abstract-method-mandatory-in-an-abstract-class-concrete-methods) | 92 | | 72 | [Can we create an object of an abstract class using the new keyword?](#can-we-create-an-object-of-an-abstract-class-using-the-new-keyword) | 93 | | 73 | [Can final methods be present in an abstract class?](#can-final-methods-be-present-in-an-abstract-class) | 94 | | 74 | [Can we define an abstract class as final?](#can-we-define-an-abstract-class-as-final) | 95 | | 75 | [Can an abstract class have a main method in Java?](#can-an-abstract-class-have-a-main-method-in-java) | 96 | | | **Inheritance & Interfaces** | 97 | | 76 | [What is inheritance, and what are the types of inheritance?](#what-is-inheritance-and-what-are-the-types-of-inheritance) | 98 | | 77 | [What class do all classes inherit from in Java?](#what-class-do-all-classes-inherit-from-in-java) | 99 | | 78 | [Why is multiple inheritance not possible in Java? (ambiguity problem)](#why-is-multiple-inheritance-not-possible-in-java-ambiguity-problem) | 100 | | 79 | [What is the use of interfaces?](#what-is-the-use-of-interfaces) | 101 | | 80 | [How are abstraction and loose coupling achieved?](#how-are-abstraction-and-loose-coupling-achieved) | 102 | | 81 | [Can an interface implement another interface in Java?](#can-an-interface-implement-another-interface-in-java) | 103 | | 82 | [What is the diamond problem in Java? How does Java's approach with interfaces solve it?](#what-is-the-diamond-problem-in-java-how-does-javas-approach-with-interfaces-solve-it) | 104 | | 83 | [What are marker interfaces? Can you provide examples?](#what-are-marker-interfaces-can-you-provide-examples) | 105 | | 84 | [Can interfaces have static initializer blocks or constructors?](#can-interfaces-have-static-initializer-blocks-or-constructors) | 106 | | 85 | [Can an interface have a static variable?](#can-an-interface-have-a-static-variable) | 107 | | 86 | [Can an interface have static nested interfaces?](#can-an-interface-have-static-nested-interfaces) | 108 | | 87 | [What is the difference between Comparable and Comparator interfaces in Java?](#what-is-the-difference-between-comparable-and-comparator-interfaces-in-java) | 109 | | 88 | [How can you achieve callback functionality using interfaces in Java?](#how-can-you-achieve-callback-functionality-using-interfaces-in-java) | 110 | | 89 | [What is a functional interface?](#what-is-a-functional-interface) | 111 | | 90 | [What are default and static methods? What is their use?](#what-are-default-and-static-methods-what-is-their-use) | 112 | | 91 | [Can a default method in an interface be overridden in an implementing class?](#can-a-default-method-in-an-interface-be-overridden-in-an-implementing-class) | 113 | | 92 | [Can an interface have fields?](#can-an-interface-have-fields) | 114 | | | **Polymorphism** | 115 | | 93 | [What is polymorphism? (types)](#what-is-polymorphism-types) | 116 | | | **Enum** | 117 | | 94 | [What is an enum? How do you declare it in Java? What are the advantages and limitations?](#what-is-an-enum-how-do-you-declare-it-in-java-what-are-the-advantages-and-limitations) | 118 | | 95 | [Can enums have methods in Java? | constructor](#can-enums-have-methods-in-java--constructor) | 119 | | 96 | [Can we create an enum object using new?](#can-we-create-an-enum-object-using-new) | 120 | | 97 | [How do you access enum constants and methods in Java?](#how-do-you-access-enum-constants-and-methods-in-java) | 121 | | 98 | [Can enums implement interfaces in Java?](#can-enums-implement-interfaces-in-java) | 122 | | 99 | [Can enums have abstract methods in Java?](#can-enums-have-abstract-methods-in-java) | 123 | | 100 | [Can enums override methods from the java.lang.Enum class in Java?](#can-enums-override-methods-from-the-javalangenum-class-in-java) | 124 | | 101 | [How can you serialize and deserialize enums in Java?](#how-can-you-serialize-and-deserialize-enums-in-java) | 125 | | | **Encapsulation** | 126 | | 102 | [What is encapsulation, and how is it implemented? What are its benefits?](#what-is-encapsulation-and-how-is-it-implemented-what-are-its-benefits) | 127 | | | **Collections and Data Structures** | 128 | | 108 | [Given an Employee class: Store in a map ensuring no duplicates.](#given-an-employee-class-store-in-a-map-ensuring-no-duplicates) | | 129 | | | **Multithreading and Concurrency** | 130 | | 116 | [What is latching with respect to multithreading?](#what-is-latching-with-respect-to-multithreading) | 131 | | 117 | [What is synchronization in Java?](#what-is-synchronization-in-java) | 132 | | 118 | [How to achieve thread safety apart from using synchronization? (Semaphore & Mutex)](#how-to-achieve-thread-safety-apart-from-using-synchronization-semaphore--mutex) | 133 | | 119 | [What is a deadlock situation in a Java program?](#what-is-a-deadlock-situation-in-a-java-program) | 134 | | 120 | [Why are wait(), notify(), and notifyAll() in Object class and not in Thread class?](#why-are-wait-notify-and-notifyall-in-object-class-and-not-in-thread-class) | 135 | | 121 | [Explain ExecutorService framework. submit vs execute?](#explain-executorservice-framework-submit-vs-execute) | 136 | | 122 | [What is the need for the Executor framework?](#what-is-the-need-for-the-executor-framework) | 137 | | 123 | [What is CompletableFuture? How is it different from Future?](#what-is-completablefuture-how-is-it-different-from-future) | 138 | | 124 | [How to create a thread pool?](#how-to-create-a-thread-pool) | 139 | | 125 | [Use of Thread dump.](#use-of-thread-dump) | 140 | | 126 | [Process vs Thread.](#process-vs-thread) | 141 | | 127 | [How to analyze thread dump.](#how-to-analyze-thread-dump) | 142 | | 128 | [Callable and Future in ExecutorServices.](#callable-and-future-in-executorservices) | 143 | | 129 | [Race Condition in threads.](#race-condition-in-threads) | 144 | | | **Synchronization (Detailed)** | 145 | | 130 | [Synchronization definition and purpose.](#synchronization-definition-and-purpose) | 146 | | 131 | [What is a critical section?](#what-is-a-critical-section) | 147 | | | **Memory and Initialization** | 148 | | 132 | [What are the memory types, and what are the GC methods? (Revisit GC Section)](#what-are-the-memory-types-and-what-are-the-gc-methods-revisit-gc-section) | 149 | | 133 | [Static loading and initialization phase.](#static-loading-and-initialization-phase) | 150 | | 134 | [Invoking a constructor.](#invoking-a-constructor) | 151 | | 135 | [Non-static loading and initialization phase.](#non-static-loading-and-initialization-phase) | 152 | | | **Factory Methods** | 153 | | 136 | [What are factory methods in Java?](#what-are-factory-methods-in-java) | 154 | | | **Miscellaneous** | 155 | | 137 | [What are this, super keywords? Using the same constructors? (Revisit Constructor Section)](#what-are-this-super-keywords-using-the-same-constructors-revisit-constructor-section) | 156 | | 138 | [Implicit casting / upcasting vs Explicit casting / downcasting.](#implicit-casting--upcasting-vs-explicit-casting--downcasting) | 157 | | 139 | [Using String... args vs. String[] args in the main method.](#using-string-args-vs-string-args-in-the-main-method) | 158 | | 140 | [Steps to create an immutable class.](#steps-to-create-an-immutable-class) | 159 | | 141 | [Static binding vs Dynamic binding.](#static-binding-vs-dynamic-binding) | 160 | | 142 | [Transient keyword.](#transient-keyword) | 161 | | 143 | [What is PostConstruct?](#what-is-postconstruct) | 162 | | | **Exception Handling** | 163 | | 144 | [What is exception propagation in Java?](#what-is-exception-propagation-in-java) | 164 | | 145 | [What is BufferUnderflowException?](#what-is-bufferunderflowexception) | 165 | | 146 | [Explain try-with-resources. Why don’t we need a finally block here?](#explain-try-with-resources-why-dont-we-need-a-finally-block-here) | 166 | | 147 | [Checked Exception vs Unchecked Exception.](#checked-exception-vs-unchecked-exception) | 167 | | | **Java 8 and Functional Programming** | 168 | | 148 | [What are Java 8 features?](#what-are-java-8-features) | 169 | | 149 | [Explain the internal functioning of streams.](#explain-the-internal-functioning-of-streams) | 170 | | 150 | [How do you implement a functional interface?](#how-do-you-implement-a-functional-interface) | 171 | | 151 | [Random generation in streams.](#random-generation-in-streams) | 172 | | | **Garbage Collection** | 173 | | 152 | [What is Garbage Collection, and why is it needed in Java?](#what-is-garbage-collection-and-why-is-it-needed-in-java) | 174 | | 153 | [How can we manually request Garbage Collection, and is it recommended?](#how-can-we-manually-request-garbage-collection-and-is-it-recommended) | 175 | | 154 | [How does finalize() work, and is it guaranteed to execute? When does GC call finalize()?](#how-does-finalize-work-and-is-it-guaranteed-to-execute-when-does-gc-call-finalize) | 176 | | 155 | [What are the different Garbage Collectors available in Java? Different ways to call GC?](#what-are-the-different-garbage-collectors-available-in-java-different-ways-to-call-gc) | 177 | | 156 | [What are Strong, Soft, Weak, and Phantom References in Java?](#what-are-strong-soft-weak-and-phantom-references-in-java) | 178 | | 157 | [How to make an object eligible for Garbage Collection?](#how-to-make-an-object-eligible-for-garbage-collection) | 179 | | 158 | [Differentiate between Heap vs Stack Memory in Java? Different parts of the heap?](#differentiate-between-heap-vs-stack-memory-in-java-different-parts-of-the-heap) | 180 | | 159 | [Which part of the memory is involved in Garbage Collection? Stack or Heap?](#which-part-of-the-memory-is-involved-in-garbage-collection-stack-or-heap) | 181 | | 160 | [How do you identify minor and major garbage collection in Java?](#how-do-you-identify-minor-and-major-garbage-collection-in-java) | 182 | | 161 | [What is the algorithm for garbage collection in Java?](#what-is-the-algorithm-for-garbage-collection-in-java) | 183 | | | **JVM Internals** | 184 | | 162 | [(Refer to external resources/notes for JVM Internals)](#refer-to-external-resourcesnotes-for-jvm-internals) | 185 | | | **Generics** | 186 | | 163 | [(Refer to external resources/notes for Generics)](#refer-to-external-resourcesnotes-for-generics) | 187 | | | **Reflection API** | 188 | | 164 | [(Refer to external resources/notes for Reflection API)](#refer-to-external-resourcesnotes-for-reflection-api) | 189 | | | **Spring Framework** | 190 | | 165 | [Bean life cycle in Spring.](#bean-life-cycle-in-spring) | 191 | | 166 | [@Qualifier and @Required.](#qualifier-and-required) | 192 | | 167 | [What are actuators, and which have you used?](#what-are-actuators-and-which-have-you-used) | 193 | | 168 | [How to handle global exceptions in Spring Boot.](#how-to-handle-global-exceptions-in-spring-boot) | 194 | | 169 | [How to access other .properties files in Spring Boot.](#how-to-access-other-properties-files-in-spring-boot) | 195 | | 170 | [How to rename application.properties and use a custom properties file.](#how-to-rename-applicationproperties-and-use-a-custom-properties-file) | 196 | | 171 | [What is advice in AOP?](#what-is-advice-in-aop) | 197 | | 172 | [ApplicationContext vs WebApplicationContext.](#applicationcontext-vs-webapplicationcontext) | 198 | | 173 | [Scopes in Spring.](#scopes-in-spring) | 199 | | 174 | [Spring Data JPA flow.](#spring-data-jpa-flow) | 200 | | 175 | [Spring design patterns.](#spring-design-patterns) | 201 | | 176 | [How to create a composite key in Spring Data JPA.](#how-to-create-a-composite-key-in-spring-data-jpa) | 202 | | 177 | [What are pointcuts in AOP?](#what-are-pointcuts-in-aop) | 203 | 204 | -------------------------------------------------------------------------------- /core-java/notes-on-enum.md: -------------------------------------------------------------------------------- 1 | # Java Enums - Complete Notes 2 | 3 | ## What are Enums? 4 | 5 | 1. Special type of class that represents a group of constants 6 | 2. Declared using the `enum` keyword 7 | 3. All enum constants are implicitly `public`, `static`, and `final` 8 | 4. Cannot use `new` to instantiate an enum 9 | 5. Can implement interfaces but cannot extend other classes 10 | 6. Can contain constructors, methods, and fields 11 | 7. Constructor must be private (implicitly if not specified) 12 | 8. Can contain abstract methods, but all constants must implement them 13 | 9. Can have instance-specific behavior by providing method implementations in constant definitions 14 | 10. Implicitly extends `java.lang.Enum` 15 | 11. Has special methods like `values()`, `valueOf()`, `ordinal()`, and `name()` 16 | 12. Can be used in switch statements 17 | 13. Thread-safe singleton implementation 18 | 14. Can be used with `EnumSet` and `EnumMap` for efficient operations 19 | 20 | ## Advantages of Using Enums 21 | 22 | 1. **Type safety**: Restricts variable to have only predefined values 23 | 2. **Readable code**: Improves clarity with named constants 24 | 3. **Singleton-like behavior**: Each enum constant is a singleton, ideal for shared constants 25 | 4. **Can have fields and methods**: Enums can have constructors, fields, and methods for complex behavior 26 | 5. **Switch-case friendly**: Works seamlessly with `switch` statements 27 | 6. **Built-in serialization support**: Enums are serializable by default 28 | 29 | ## Limitations of Enums 30 | 31 | 1. **Cannot extend classes**: Enums implicitly extend `java.lang.Enum`, so they can't extend any other class 32 | 2. **Fixed constants**: Enum constants are fixed at compile time—no dynamic addition 33 | 3. **Not suitable for all use cases**: Enums are ideal for fixed sets; dynamic or frequently changing values aren't a good fit 34 | 4. **Cannot clone**: Enum instances can't be cloned 35 | 5. **Limited flexibility**: Overengineering for simple constants if not used wisely 36 | 37 | ## Method Overriding in Enums 38 | 39 | ### Can enums override methods from `java.lang.Enum`? 40 | **No**, enums **cannot override** methods from `java.lang.Enum` because it's a **final class**. 41 | 42 | ### Can enums override methods from `java.lang.Object`? 43 | **Yes**, enums in Java **can override methods from `java.lang.Object`**, such as: 44 | - `toString()` 45 | - `equals()` 46 | - `hashCode()` 47 | - `clone()` (though enums can't be cloned) 48 | - `finalize()` (deprecated) 49 | 50 | Example: 51 | ```java 52 | enum Color { 53 | RED, GREEN, BLUE; 54 | 55 | @Override 56 | public String toString() { 57 | return "Color: " + name(); 58 | } 59 | } 60 | ``` 61 | 62 | ## Serialization and Deserialization 63 | 64 | 1. Enums are **serializable by default** 65 | 2. Use `ObjectOutputStream` and `ObjectInputStream` for serialization and deserialization 66 | 3. In JSON (e.g., Jackson), just use `@JsonProperty` or default mapping works out-of-the-box 67 | 68 | ## Examples 69 | 70 | ### Example 1: Basic Enum Usage 71 | 72 | ```java 73 | import java.util.EnumSet; 74 | import java.util.EnumMap; 75 | import java.util.Map; 76 | 77 | public class EnumExample { 78 | 79 | // Define enum Day with constants 80 | enum Day { 81 | MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY 82 | } 83 | 84 | public static void main(String[] args) { 85 | // 1. values() - Get all enum constants 86 | System.out.println("All days:"); 87 | for (Day day : Day.values()) { 88 | System.out.print(day + " "); 89 | } 90 | System.out.println("\n"); 91 | 92 | // 2. valueOf() - Convert string to enum constant 93 | Day d = Day.valueOf("MONDAY"); 94 | System.out.println("valueOf(\"MONDAY\") returns: " + d); // valueOf("MONDAY") returns: MONDAY 95 | 96 | // 3. ordinal() - Get index of enum constant 97 | System.out.println("Ordinal of MONDAY: " + Day.MONDAY.ordinal()); // 0 98 | System.out.println("Ordinal of SUNDAY: " + Day.SUNDAY.ordinal()); // 6 99 | 100 | // 4. name() - Get exact name of enum constant 101 | System.out.println("Name of Day.FRIDAY: " + Day.FRIDAY.name()); 102 | 103 | System.out.println(); 104 | 105 | // Using EnumSet for weekend days 106 | EnumSet weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY); 107 | System.out.println("Weekend days using EnumSet:"); 108 | for (Day day : weekend) { 109 | System.out.print(day + " "); 110 | } 111 | System.out.println("\n"); 112 | 113 | // Using EnumMap to map days to tasks 114 | EnumMap tasks = new EnumMap<>(Day.class); 115 | tasks.put(Day.MONDAY, "Write report"); 116 | tasks.put(Day.FRIDAY, "Submit report"); 117 | 118 | System.out.println("Tasks mapped to days using EnumMap:"); 119 | for (Map.Entry entry : tasks.entrySet()) { 120 | System.out.println(entry.getKey() + ": " + entry.getValue()); 121 | } 122 | } 123 | } 124 | ``` 125 | 126 | ### Example 2: Enum with Abstract Methods 127 | 128 | ```java 129 | enum Operation { 130 | ADD { 131 | @Override 132 | public int apply(int a, int b) { 133 | return a + b; 134 | } 135 | }, 136 | SUBTRACT { 137 | @Override 138 | public int apply(int a, int b) { 139 | return a - b; 140 | } 141 | }, 142 | MULTIPLY { 143 | @Override 144 | public int apply(int a, int b) { 145 | return a * b; 146 | } 147 | }; 148 | 149 | // Abstract method 150 | public abstract int apply(int a, int b); 151 | } 152 | 153 | //main 154 | public class Main { 155 | public static void main(String[] args) { 156 | int a = 5, b = 3; 157 | 158 | System.out.println(Operation.ADD.apply(a, b)); // 8 159 | System.out.println(Operation.SUBTRACT.apply(a, b)); // 2 160 | System.out.println(Operation.MULTIPLY.apply(a, b)); // 15 161 | } 162 | } 163 | ``` 164 | 165 | 166 | 167 | 168 | 169 | ### Example: Main Method in Different Structures 170 | 171 | ```java 172 | class A { 173 | public static void main(String[] s) { 174 | System.out.println("A-main"); 175 | } 176 | } 177 | 178 | abstract class B { 179 | public static void main(String[] s) { 180 | System.out.println("B-main"); 181 | } 182 | } 183 | 184 | enum C { 185 | ; // Empty enum body 186 | public static void main(String[] s) { 187 | System.out.println("C-main"); 188 | } 189 | } 190 | 191 | interface K { 192 | public static void main(String[] s) { 193 | System.out.println("K-main"); 194 | } 195 | } 196 | ``` 197 | 198 | > All of these classes can be compiled and their main methods can be executed. 199 | 200 | [Back to Top](#table-of-contents) -------------------------------------------------------------------------------- /core-java/notes-on-oops-concepts.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Table of Contents 4 | 5 | | # | Question | 6 | |-----|--------------------------------------------------------------------------| 7 | | 1 | [What is Association in OOP?](#what-is-association-in-oop) | 8 | | 2 | [What is Aggregation in OOP?](#what-is-aggregation-in-oop) | 9 | | 3 | [What is Composition in OOP?](#what-is-composition-in-oop) | 10 | | 4 | [Differences between Association, Aggregation, and Composition](#differences-between-association-aggregation-and-composition) | 11 | | 5 | [Notes On Enum](#notes-on-enum) | 12 | | 6 | [Java Abstraction, Interfaces, Inheritance & Diamond Problem](#java-abstraction-interfaces-inheritance--diamond-problem) | 13 | | 7 | [How are Abstraction and Loose Coupling Achieved?](#1-how-are-abstraction-and-loose-coupling-achieved) | 14 | | 8 | [What is the Use of Interfaces?](#2-what-is-the-use-of-interfaces) | 15 | | 9 | [What is Inheritance and Types of Inheritance?](#3-what-is-inheritance-and-types-of-inheritance) | 16 | | 10 | [Why is Multiple Inheritance Not Possible in Java?](#4-why-is-multiple-inheritance-not-possible-in-java) | 17 | | 11 | [What is the Diamond Problem and How Does Java Solve It?](#5-what-is-the-diamond-problem-and-how-does-java-solve-it) | 18 | | 12 | [Java Multiple Inheritance: Code Examples](#no-error-in-this-program) | 19 | 20 | --- 21 | 22 | 23 | ## 1. Association 24 | 25 | Represents a "uses-a" or "has-a" relationship. 26 | Objects can be related without ownership. 27 | May be unidirectional or bidirectional. 28 | Objects can exist independently. 29 | UML Notation: Plain line 30 | 31 | ### Example: One-to-Many Association (Doctor ↔ Patients) 32 | 33 | ```java 34 | class Patient { 35 | private String name; 36 | 37 | Patient(String name) { 38 | this.name = name; 39 | } 40 | 41 | String getName() { 42 | return name; 43 | } 44 | } 45 | 46 | class Doctor { 47 | private String name; 48 | 49 | Doctor(String name) { 50 | this.name = name; 51 | } 52 | 53 | void treat(Patient patient) { 54 | System.out.println(name + " is treating patient " + patient.getName()); 55 | } 56 | } 57 | 58 | public class AssociationDemo { 59 | public static void main(String[] args) { 60 | Doctor doctor = new Doctor("Dr. Sharma"); 61 | Patient p1 = new Patient("John"); 62 | Patient p2 = new Patient("Sara"); 63 | 64 | // One-to-Many: A doctor can treat many patients 65 | doctor.treat(p1); 66 | doctor.treat(p2); 67 | } 68 | } 69 | ``` 70 | 71 | Additional Examples: 72 | 73 | * One-to-One: A person has one passport. 74 | * Many-to-One: Many students belong to one school. 75 | * Many-to-Many: Students enroll in many courses and vice versa. 76 | 77 | --- 78 | 79 | ## 2. Aggregation 80 | 81 | Represents a "has-a" relationship. 82 | Weak association – the child can exist independently. 83 | Implemented via object reference. 84 | Represented by a hollow diamond in UML diagrams. 85 | 86 | ### Example: Aggregation (Team has Players) 87 | 88 | ```java 89 | import java.util.List; 90 | import java.util.ArrayList; 91 | 92 | class Player { 93 | private String name; 94 | 95 | Player(String name) { 96 | this.name = name; 97 | } 98 | 99 | String getName() { 100 | return name; 101 | } 102 | } 103 | 104 | class Team { 105 | private String teamName; 106 | private List players; 107 | 108 | Team(String teamName) { 109 | this.teamName = teamName; 110 | this.players = new ArrayList<>(); 111 | } 112 | 113 | void addPlayer(Player player) { 114 | players.add(player); // Aggregation: Player is referenced but not owned 115 | } 116 | 117 | void showTeam() { 118 | System.out.println("Team: " + teamName); 119 | for (Player p : players) { 120 | System.out.println("- " + p.getName()); 121 | } 122 | } 123 | } 124 | 125 | public class AggregationDemo { 126 | public static void main(String[] args) { 127 | Player p1 = new Player("Alice"); 128 | Player p2 = new Player("Bob"); 129 | 130 | Team team = new Team("Warriors"); 131 | team.addPlayer(p1); 132 | team.addPlayer(p2); 133 | 134 | team.showTeam(); 135 | 136 | // Players continue to exist even if the Team is disbanded 137 | } 138 | } 139 | ``` 140 | 141 | --- 142 | 143 | ## 3. Composition 144 | 145 | Composition is a strong form of aggregation, where one class owns another class and is responsible for its lifecycle. 146 | Represents a "part-of" or strong has-a relationship. 147 | Strong association – the child cannot exist without the parent. 148 | Represented by a solid diamond in UML diagrams. 149 | 150 | ### Example: Composition (Car has Engine) 151 | 152 | ```java 153 | class Engine { 154 | private String type; 155 | 156 | Engine(String type) { 157 | this.type = type; 158 | } 159 | 160 | void start() { 161 | System.out.println("Engine of type " + type + " started."); 162 | } 163 | } 164 | 165 | class Car { 166 | private Engine engine; 167 | 168 | Car() { 169 | engine = new Engine("V8"); // Composition: Engine created and owned by Car 170 | } 171 | 172 | void drive() { 173 | engine.start(); 174 | System.out.println("Car is driving."); 175 | } 176 | } 177 | 178 | public class CompositionDemo { 179 | public static void main(String[] args) { 180 | Car car = new Car(); 181 | car.drive(); 182 | 183 | // If the Car is destroyed, the Engine is also destroyed 184 | } 185 | } 186 | ``` 187 | 188 | --- 189 | 190 | ## Differences between Association, Aggregation, and Composition 191 | 192 | | Feature | Association | Aggregation | Composition | 193 | | ------------ | -------------------- | ----------------------------- | -------------------------------- | 194 | | Type | General relationship | Weak "has-a" | Strong "has-a" | 195 | | Dependency | No dependency | Child can exist independently | Child cannot exist independently | 196 | | Lifecycle | Independent | Independent | Dependent | 197 | | UML Notation | Plain Line | Hollow diamond | Solid diamond | 198 | | Example | Student ↔ School | Department → Professor | House → Room | 199 | 200 | --- 201 | 202 | 203 | 204 | 205 | 206 |
207 | 208 | ## Java: Abstraction, Interfaces, Inheritance & Diamond Problem 209 | 210 | ## 1. How are Abstraction and Loose Coupling Achieved? 211 | 212 | ### Abstraction 213 | **Definition**: Hiding implementation details while showing only essential features to the user. 214 | 215 | **Achieved through**: 216 | - **Abstract Classes**: Classes that cannot be instantiated and may contain abstract methods 217 | - **Interfaces**: Contracts that define what a class must do, not how it does it 218 | - **Access Modifiers**: Control visibility of class members 219 | 220 | **Example**: 221 | ```java 222 | // Abstract class providing abstraction 223 | abstract class Vehicle { 224 | abstract void start(); // What to do (not how) 225 | 226 | public void stop() { // Common implementation 227 | System.out.println("Vehicle stopped"); 228 | } 229 | } 230 | 231 | class Car extends Vehicle { 232 | void start() { // How to do it 233 | System.out.println("Car engine started"); 234 | } 235 | } 236 | ``` 237 | 238 | ### Loose Coupling 239 | **Definition**: Reducing dependencies between classes/modules so changes in one don't heavily impact others. 240 | 241 | **Achieved through**: 242 | - **Interfaces**: Program to interfaces, not implementations 243 | - **Dependency Injection**: Provide dependencies from outside 244 | - **Abstract Classes**: Use abstract types instead of concrete classes 245 | 246 | **Example**: 247 | ```java 248 | // Loose coupling with interfaces 249 | interface PaymentProcessor { 250 | void processPayment(double amount); 251 | } 252 | 253 | class CreditCardProcessor implements PaymentProcessor { 254 | public void processPayment(double amount) { 255 | // Credit card logic 256 | } 257 | } 258 | 259 | class PayPalProcessor implements PaymentProcessor { 260 | public void processPayment(double amount) { 261 | // PayPal logic 262 | } 263 | } 264 | 265 | class OrderService { 266 | private PaymentProcessor processor; 267 | 268 | // Loosely coupled - can work with any payment processor 269 | public OrderService(PaymentProcessor processor) { 270 | this.processor = processor; 271 | } 272 | 273 | public void processOrder(double amount) { 274 | processor.processPayment(amount); 275 | } 276 | } 277 | ``` 278 | 279 | ## 2. What is the Use of Interfaces? 280 | 281 | ### Primary Uses: 282 | 283 | 1. **Achieve Multiple Inheritance**: Java classes can implement multiple interfaces 284 | 2. **Contract Definition**: Define what methods a class must implement 285 | 3. **Abstraction**: Hide implementation details 286 | 4. **Loose Coupling**: Reduce dependencies between classes 287 | 5. **Polymorphism**: Treat different objects uniformly 288 | 6. **API Design**: Define consistent APIs across different implementations 289 | 290 | ### Practical Examples: 291 | 292 | **Example 1: Multiple Inheritance of Type** 293 | **Example 2: Polymorphism** 294 | 295 | 296 | ## 3. What is Inheritance and Types of Inheritance? 297 | 298 | ### Inheritance 299 | **Definition**: Mechanism where a new class (child/subclass) inherits properties and methods from an existing class (parent/superclass). 300 | 301 | **Benefits**: 302 | - Code reusability 303 | - Method overriding 304 | - Polymorphism 305 | - Hierarchical classification 306 | 307 | ### Types of Inheritance: 308 | 309 | #### 1. Single Inheritance 310 | One class inherits from one parent class. 311 | ```java 312 | class Animal { 313 | void eat() { System.out.println("Animal eats"); } 314 | } 315 | 316 | class Dog extends Animal { 317 | void bark() { System.out.println("Dog barks"); } 318 | } 319 | ``` 320 | 321 | #### 2. Multilevel Inheritance 322 | Chain of inheritance (grandparent → parent → child). 323 | ```java 324 | class Animal { 325 | void breathe() { System.out.println("Breathing"); } 326 | } 327 | 328 | class Mammal extends Animal { 329 | void warmBlooded() { System.out.println("Warm blooded"); } 330 | } 331 | 332 | class Dog extends Mammal { 333 | void bark() { System.out.println("Barking"); } 334 | } 335 | ``` 336 | 337 | #### 3. Hierarchical Inheritance 338 | Multiple classes inherit from one parent class. 339 | ```java 340 | class Animal { 341 | void move() { System.out.println("Animal moves"); } 342 | } 343 | 344 | class Dog extends Animal { 345 | void bark() { System.out.println("Dog barks"); } 346 | } 347 | 348 | class Cat extends Animal { 349 | void meow() { System.out.println("Cat meows"); } 350 | } 351 | ``` 352 | 353 | #### 4. Multiple Inheritance (NOT supported in Java for classes) 354 | One class inheriting from multiple parent classes. 355 | ```java 356 | // NOT POSSIBLE in Java with classes 357 | // class Child extends Parent1, Parent2 { } // COMPILATION ERROR 358 | 359 | // But possible with interfaces 360 | interface Interface1 { void method1(); } 361 | interface Interface2 { void method2(); } 362 | class Child implements Interface1, Interface2 { 363 | public void method1() { } 364 | public void method2() { } 365 | } 366 | ``` 367 | 368 | #### 5. Hybrid Inheritance (NOT directly supported) 369 | Combination of multiple inheritance types. 370 | 371 | ## 4. Why is Multiple Inheritance Not Possible in Java? 372 | 373 | ### The Ambiguity Problem 374 | 375 | **Reasons**: 376 | 1. **Diamond Problem**: Ambiguity when same method exists in multiple parent classes 377 | 2. **Complexity**: Makes the language complex and error-prone 378 | 3. **Compilation Issues**: Compiler cannot decide which method to inherit 379 | 380 | **Example of the Problem**: 381 | ```java 382 | // This is NOT valid Java code - just for illustration 383 | class A { 384 | void display() { System.out.println("A"); } 385 | } 386 | 387 | class B extends A { 388 | void display() { System.out.println("B"); } 389 | } 390 | 391 | class C extends A { 392 | void display() { System.out.println("C"); } 393 | } 394 | 395 | // If this were allowed (IT'S NOT): 396 | class D extends B, C { // COMPILATION ERROR 397 | // Which display() method should D inherit? 398 | // B's display() or C's display()? 399 | // This creates ambiguity! 400 | } 401 | ``` 402 | 403 | **Java's Solution**: Use interfaces for multiple inheritance of type, not implementation. 404 | 405 | ## 5. What is the Diamond Problem and How Does Java Solve It? 406 | 407 | ### Diamond Problem 408 | **Definition**: Occurs when a class inherits from two classes that have a common base class, creating ambiguity about which version of inherited methods to use. 409 | 410 | **Visual Representation**: 411 | ``` 412 | A 413 | / \ 414 | B C 415 | \ / 416 | D 417 | ``` 418 | 419 | ### The Problem Scenario: 420 | ```java 421 | // Hypothetical scenario (NOT valid Java) 422 | class A { 423 | void method() { System.out.println("A"); } 424 | } 425 | 426 | class B extends A { 427 | void method() { System.out.println("B"); } 428 | } 429 | 430 | class C extends A { 431 | void method() { System.out.println("C"); } 432 | } 433 | 434 | // IF multiple inheritance were allowed: 435 | class D extends B, C { // NOT ALLOWED 436 | // Which method() should be inherited? 437 | // Ambiguity: B's method() or C's method()? 438 | } 439 | ``` 440 | 441 | ### Java's Solutions: 442 | 443 | #### 1. No Multiple Inheritance for Classes 444 | Java simply doesn't allow multiple class inheritance. 445 | 446 | #### 2. Multiple Inheritance with Interfaces 447 | 448 | When diamond problem occurs with interfaces: 449 | - Interface Default Methods (Java 8+) 450 | 451 | ```java 452 | interface A { 453 | default void method() { System.out.println("A"); } 454 | } 455 | 456 | interface B extends A { 457 | default void method() { System.out.println("B"); } 458 | } 459 | 460 | interface C extends A { 461 | default void method() { System.out.println("C"); } 462 | } 463 | 464 | class D implements B, C { 465 | // Must resolve the conflict explicitly 466 | public void method() { 467 | B.super.method(); // Explicitly call B's method 468 | // or C.super.method(); // or C's method 469 | // or provide own implementation 470 | } 471 | } 472 | ``` 473 | ### Key Points: 474 | - **Classes**: No multiple inheritance allowed - prevents diamond problem 475 | - **Interfaces**: Multiple inheritance allowed, but conflicts must be resolved explicitly 476 | - **Compiler Enforcement**: Java compiler forces explicit resolution of ambiguous situations 477 | - **Clean Design**: Encourages better design patterns and loose coupling 478 | 479 | 480 | ## no error in this program 481 | 482 | ```java 483 | 484 | interface EarthLike { 485 | void Rotation(); // Abstract method (no default keyword) 486 | } 487 | 488 | interface MarsLike { 489 | void Rotation(); // Same abstract method signature 490 | } 491 | 492 | class SatelliteBody implements EarthLike, MarsLike { 493 | @Override 494 | public void Rotation() { 495 | System.out.println("Resolved ambiguity: Satellite rotates uniquely."); 496 | } 497 | } 498 | 499 | public class Main { 500 | public static void main(String[] args) { 501 | SatelliteBody satellite = new SatelliteBody(); 502 | satellite.Rotation(); // Output: Resolved ambiguity: Satellite rotates uniquely. 503 | } 504 | } 505 | 506 | ``` 507 | ## code will shows error here 508 | 509 | ```java 510 | class A { 511 | void method() { System.out.println("A"); } 512 | } 513 | 514 | abstract class B extends A { 515 | abstract void method2(); 516 | } 517 | 518 | abstract class C extends A { 519 | abstract void method2(); 520 | } 521 | 522 | class D extends B, C { // ❌ NOT ALLOWED 523 | // Which method() should be inherited? 524 | } 525 | 526 | 527 | ``` 528 | 529 | 530 | ## valid code only 531 | ```java 532 | abstract class B { 533 | void common() { 534 | System.out.println("B"); 535 | } 536 | } 537 | 538 | interface C { 539 | void extra(); 540 | } 541 | 542 | class D extends B implements C { 543 | public void extra() { 544 | System.out.println("C's method"); 545 | } 546 | } 547 | 548 | ``` 549 | 550 | ```java 551 | interface MyInterface { 552 | static void staticMethod() { 553 | System.out.println("Static method in interface"); 554 | } 555 | } 556 | 557 | class MyClass implements MyInterface { 558 | // No access to staticMethod() directly 559 | } 560 | 561 | public class Test { 562 | public static void main(String[] args) { 563 | // MyClass.staticMethod(); ❌ Compile-time error 564 | // new MyClass().staticMethod(); ❌ Compile-time error 565 | 566 | MyInterface.staticMethod(); // ✅ Correct usage 567 | } 568 | } 569 | 570 | ``` 571 | 572 | ```java 573 | // Parent class with a static method 574 | class Parent { 575 | static void greet() { // Static method in Parent 576 | System.out.println("Hello from Parent"); 577 | } 578 | } 579 | 580 | // Child class that hides the static method of Parent 581 | class Child extends Parent { 582 | static void greet() { // Static method in Child (hides Parent's method, doesn't override it) 583 | System.out.println("Hello from Child"); 584 | } 585 | } 586 | 587 | public class Test { 588 | public static void main(String[] args) { 589 | Parent p = new Child(); // Reference is of type Parent, object is of type Child 590 | p.greet(); // Calls Parent.greet() because static methods are resolved at compile-time by reference type 591 | // This is method hiding, not overriding. So output will be: Hello from Parent 592 | } 593 | } 594 | 595 | ``` -------------------------------------------------------------------------------- /core-java/spring-boot-notes.md: -------------------------------------------------------------------------------- 1 | # Spring Boot and Its Key Modules 2 | 3 | ## Spring Boot Core Concepts 4 | 5 | ### Spring Boot Basics 6 | 1. Convention over configuration framework 7 | 2. Standalone applications with embedded servers 8 | 3. Starters provide dependency descriptors for common functionality 9 | 4. Auto-configuration attempts to configure beans based on classpath 10 | 5. `@SpringBootApplication` combines `@Configuration`, `@EnableAutoConfiguration`, and `@ComponentScan` 11 | 6. Property-based configuration with sensible defaults 12 | 7. Spring Boot applications can be run as executable jars 13 | 8. `SpringApplication` class bootstraps the application 14 | 9. Profiles allow for environment-specific configurations 15 | 10. Externalized configuration with hierarchical property resolution 16 | 17 | ### Auto-Configuration 18 | 1. Activated by `@EnableAutoConfiguration` or `@SpringBootApplication` 19 | 2. Configures beans based on classpath, properties, and existing beans 20 | 3. Conditional annotations control when auto-configuration is applied 21 | 4. `@ConditionalOnClass`, `@ConditionalOnMissingBean`, `@ConditionalOnProperty` most commonly used 22 | 5. Can be disabled for specific classes with `@EnableAutoConfiguration(exclude={Class})` 23 | 6. Can be examined with `--debug` flag to see what was auto-configured 24 | 7. Custom auto-configuration created with `@Configuration` and registered in `META-INF/spring.factories` 25 | 8. Order can be controlled with `@AutoConfigureBefore`, `@AutoConfigureAfter` 26 | 9. Provides sensible defaults but allows overriding 27 | 10. Auto-configuration classes are loaded from JAR files in `META-INF/spring.factories` 28 | 29 | ### Spring Boot Configuration 30 | 1. `application.properties` or `application.yml` for configuration 31 | 2. Environment-specific configs: `application-{profile}.properties` 32 | 3. Configuration hierarchy: command line args > OS environment variables > application properties 33 | 4. `@ConfigurationProperties` binds external properties to Java beans 34 | 5. Type-safe configuration with `@ConfigurationProperties` 35 | 6. Relaxed binding supports various naming formats (camelCase, kebab-case, etc.) 36 | 7. `@Value` for simple property injection 37 | 8. Property validation with `@Validated` and JSR-303 annotations 38 | 9. Configuration files can be placed in `/config` subdirectory or current directory 39 | 10. YAML support for more structured configuration 40 | 41 | ### Spring Boot Actuator 42 | 1. Production-ready features for monitoring and managing applications 43 | 2. Health checks with customizable health indicators 44 | 3. Metrics collection with support for various monitoring systems 45 | 4. Audit events capturing with AuditEventRepository 46 | 5. HTTP endpoints for runtime information (/health, /info, /metrics, etc.) 47 | 6. Secured by default, requires explicit exposure 48 | 7. Customizable using properties and custom endpoints 49 | 8. JMX support for management 50 | 9. Remote shell access (removed in later versions) 51 | 10. Distributed tracing integration 52 | 53 | ## Spring Boot Modules 54 | 55 | ### Spring MVC (Web) 56 | 1. Part of `spring-boot-starter-web` 57 | 2. Embedded Tomcat, Jetty, or Undertow server 58 | 3. Auto-configures DispatcherServlet, error pages, and common web features 59 | 4. JSON serialization with Jackson by default 60 | 5. Static resources served from `/static`, `/public`, `/resources`, or `/META-INF/resources` 61 | 6. Templates with Thymeleaf, FreeMarker, etc. 62 | 7. `@RestController` combines `@Controller` and `@ResponseBody` 63 | 8. `@RequestMapping` maps HTTP requests to handler methods 64 | 9. Content negotiation and message conversion 65 | 10. Custom error handling with `@ControllerAdvice` and `@ExceptionHandler` 66 | 67 | ### Spring WebFlux 68 | 1. Reactive alternative to Spring MVC 69 | 2. Non-blocking, reactive streams-based 70 | 3. Part of `spring-boot-starter-webflux` 71 | 4. Uses Netty by default instead of Tomcat 72 | 5. Router functions as alternative to annotated controllers 73 | 6. `WebClient` as reactive alternative to `RestTemplate` 74 | 7. Reactive data repositories supported 75 | 8. `Mono` for 0-1 elements, `Flux` for 0-n elements 76 | 9. Cannot be used alongside Spring MVC in the same application 77 | 10. Best for high concurrency with limited threads 78 | 79 | ### Spring Data 80 | 1. Repository abstraction to reduce boilerplate code 81 | 2. Supports various databases (JPA, MongoDB, Redis, etc.) 82 | 3. Query methods derived from method names 83 | 4. `@Query` for custom queries 84 | 5. Pagination and sorting with `Pageable` 85 | 6. Auditing with `@CreatedDate`, `@LastModifiedDate`, etc. 86 | 7. Custom repository implementations 87 | 8. Transaction management 88 | 9. Specification API for dynamic queries 89 | 10. Multiple persistence modules can coexist 90 | 91 | ### Spring Security 92 | 1. Authentication and authorization framework 93 | 2. Auto-configured with sensible defaults 94 | 3. Form-based, Basic, OAuth2, and JWT authentication 95 | 4. Method-level security with `@PreAuthorize`, `@PostAuthorize` 96 | 5. CSRF protection enabled by default 97 | 6. Session fixation protection 98 | 7. Security headers automatically applied 99 | 8. `WebSecurityConfigurerAdapter` for custom configuration (deprecated in later versions) 100 | 9. User details service for authentication 101 | 10. Role-based and permission-based authorization 102 | 103 | ### Spring Batch 104 | 1. Framework for batch processing 105 | 2. Job, Step, ItemReader, ItemProcessor, ItemWriter abstractions 106 | 3. Transaction management for steps 107 | 4. Restart, skip, and retry capabilities 108 | 5. Chunk-based processing for efficiency 109 | 6. Parallel processing with partitioning 110 | 7. Job repository for metadata storage 111 | 8. JobLauncher to run jobs 112 | 9. Listeners for various batch events 113 | 10. Integration with scheduling frameworks 114 | 115 | ### Spring Integration 116 | 1. Implementation of Enterprise Integration Patterns 117 | 2. Message-based integration framework 118 | 3. Channel adapters for various protocols 119 | 4. Message transformers and routers 120 | 5. Message endpoints 121 | 6. Gateways to invoke services via messaging 122 | 7. Message channels (direct, queue, priority, etc.) 123 | 8. Java DSL for fluent configuration 124 | 9. XML configuration support 125 | 10. Integration with external systems 126 | 127 | ### Spring Cloud 128 | 1. Tools for common distributed system patterns 129 | 2. Service discovery with Eureka 130 | 3. Client-side load balancing with Ribbon 131 | 4. Circuit breaker with Resilience4j or Hystrix 132 | 5. Distributed configuration with Config Server 133 | 6. API gateway with Spring Cloud Gateway or Zuul 134 | 7. Distributed tracing with Sleuth and Zipkin 135 | 8. Stream processing with Spring Cloud Stream 136 | 9. Contract testing with Spring Cloud Contract 137 | 10. OAuth2 integration with Spring Cloud Security 138 | 139 | ### Spring Testing 140 | 1. `@SpringBootTest` for integration testing 141 | 2. TestRestTemplate for HTTP client testing 142 | 3. MockMvc for server-side testing without HTTP 143 | 4. WebTestClient for reactive applications 144 | 5. Slice tests (`@WebMvcTest`, `@DataJpaTest`, etc.) for focused testing 145 | 6. TestPropertySource for test-specific properties 146 | 7. OutputCapture for testing console output 147 | 8. MockBean to replace beans with mocks 148 | 9. ApplicationContextRunner for testing auto-configuration 149 | 10. Random port testing with `@LocalServerPort` 150 | 151 | ### Spring Boot Devtools 152 | 1. Automatic application restart when files change 153 | 2. LiveReload server for browser refresh 154 | 3. Global settings with devtools properties 155 | 4. Remote application debugging 156 | 5. Developer tools excluded from production builds 157 | 6. Property defaults overrides 158 | 7. Automatic H2 console enablement 159 | 8. Remote update and restart support 160 | 9. File system file watcher 161 | 10. Template cache disabled for development 162 | 163 | ### Spring Boot Actuator 164 | 1. Health indicators for application health 165 | 2. Info endpoints for application information 166 | 3. Metrics with Micrometer 167 | 4. Audit events for security auditing 168 | 5. HTTP tracing for request/response logging 169 | 6. Beans endpoint for application context beans 170 | 7. Environment endpoint for configuration properties 171 | 8. Loggers endpoint for changing log levels 172 | 9. Mappings endpoint for RequestMapping information 173 | 10. Customizable via properties and code extensions 174 | 175 | ### Messaging with Spring Boot 176 | 1. JMS support with `spring-boot-starter-activemq` or `spring-boot-starter-artemis` 177 | 2. AMQP support with `spring-boot-starter-amqp` (RabbitMQ) 178 | 3. Kafka support with `spring-boot-starter-kafka` 179 | 4. `@JmsListener` for consuming JMS messages 180 | 5. `@RabbitListener` for consuming AMQP messages 181 | 6. `@KafkaListener` for consuming Kafka messages 182 | 7. Template classes for sending messages (JmsTemplate, RabbitTemplate, KafkaTemplate) 183 | 8. Message converters for serialization/deserialization 184 | 9. Container factories for listener configuration 185 | 10. Error handling with error handlers and retry templates 186 | -------------------------------------------------------------------------------- /exception-handling/interview-questions.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Java Exception Handling Comprehensive Guide 4 | 5 | --- 6 | 7 | This guide provides a detailed examination of Java exception handling, from basic concepts to advanced techniques. It covers the exception hierarchy, handling mechanisms, inheritance implications, and best practices for effective error management in Java applications. 8 | 9 | --- 10 | 11 | | # | Question | 12 | |---|----------| 13 | | **CORE EXCEPTION HANDLING CONCEPTS** | 14 | | 1 | [What is an exception in Java?](#what-is-an-exception-in-java) | 15 | | 2 | [What is the difference between errors and exceptions?](#what-is-the-difference-between-errors-and-exceptions) | 16 | | 3 | [What is the exception hierarchy in Java?](#what-is-the-exception-hierarchy-in-java) | 17 | | 4 | [What are checked and unchecked exceptions?](#what-are-checked-and-unchecked-exceptions) | 18 | | 5 | [What are handled and unhandled exceptions?](#what-are-handled-and-unhandled-exceptions) | 19 | | 6 | [What is the difference between runtime and compile-time exceptions?](#what-is-the-difference-between-runtime-and-compile-time-exceptions) | 20 | | 7 | [How does exception propagation work in Java?](#how-does-exception-propagation-work-in-java) | 21 | | 8 | [What is the purpose of the Throwable class?](#what-is-the-purpose-of-the-throwable-class) | 22 | | 9 | [Important classes and methods needed to know in exception handling?](#important-classes-and-methods-needed-to-know-in-exception-handling) | 23 | | **EXCEPTION HANDLING MECHANISMS** | 24 | | 10 | [How does the try-catch-finally block work in Java?](#how-does-the-try-catch-finally-block-work-in-java) | 25 | | 11 | [When should we use try, catch, finally, and finalize()?](#when-should-we-use-try-catch-finally-and-finalize) | 26 | | 12 | [What happens if an exception occurs inside a finally block?](#what-happens-if-an-exception-occurs-inside-a-finally-block) | 27 | | 13 | [Can a finally block contain a return statement?](#can-a-finally-block-contain-a-return-statement) | 28 | | 14 | [What is the difference between throw and throws?](#what-is-the-difference-between-throw-and-throws) | 29 | | 15 | [Can we have multiple catch blocks?](#can-we-have-multiple-catch-blocks) | 30 | | 16 | [What is a nested try-catch block?](#what-is-a-nested-try-catch-block) | 31 | | 17 | [How does try-with-resources work?](#how-does-try-with-resources-work) | 32 | | 18 | [Can we have the statement in between try and catch?](#can-we-have-the-statement-in-between-try-and-catch) | 33 | | **ADVANCED EXCEPTION HANDLING** | 34 | | 19 | [Can we catch multiple exceptions in a single catch block?](#can-we-catch-multiple-exceptions-in-a-single-catch-block) | 35 | | 20 | [What are custom exceptions?](#what-are-custom-exceptions) | 36 | | 21 | [How do you rethrow an exception in Java?](#how-do-you-rethrow-an-exception-in-java) | 37 | | 22 | [What is exception chaining?](#what-is-exception-chaining) | 38 | | 23 | [What is the impact of exceptions on performance?](#what-is-the-impact-of-exceptions-on-performance) | 39 | | 24 | [Can an exception be thrown from a constructor?](#can-an-exception-be-thrown-from-a-constructor) | 40 | | 25 | [Can an exception be thrown from a static block?](#can-an-exception-be-thrown-from-a-static-block) | 41 | | 26 | [Can we have a try block without a catch block?](#can-we-have-a-try-block-without-a-catch-block) | 42 | | 27 | [What happens if an exception is not handled in Java?](#what-happens-if-an-exception-is-not-handled-in-java) | 43 | | 28 | [How do you suppress exceptions in Java?](#how-do-you-suppress-exceptions-in-java) | 44 | | 29 | [Can we use multiple try-with-resources statements in a single block?](#can-we-use-multiple-try-with-resources-statements-in-a-single-block) | 45 | | **RETHROWING EXCEPTIONS** | 46 | | 30 | [What is rethrowing an exception?](#what-is-rethrowing-an-exception) | 47 | | 31 | [Can we rethrow a checked exception without declaring it?](#can-we-rethrow-a-checked-exception-without-declaring-it) | 48 | | 32 | [What happens if we catch a checked exception and rethrow a different one?](#what-happens-if-we-catch-a-checked-exception-and-rethrow-a-different-one) | 49 | | 33 | [How do we preserve the original stack trace when rethrowing?](#how-do-we-preserve-the-original-stack-trace-when-rethrowing) | 50 | | 34 | [What's the difference between throw e and throw new Exception(e)?](#whats-the-difference-between-throw-e-and-throw-new-exceptione) | 51 | | **EXCEPTION HANDLING AND INHERITANCE** | 52 | | 35 | [How does exception handling work in method overriding?](#how-does-exception-handling-work-in-method-overriding) | 53 | | 36 | [Can a subclass throw a new checked exception not in the parent?](#can-a-subclass-throw-a-new-checked-exception-not-in-the-parent) | 54 | | 37 | [Can a subclass remove checked exceptions from its throws clause?](#can-a-subclass-remove-checked-exceptions-from-its-throws-clause) | 55 | | 38 | [What if a superclass constructor throws an exception?](#what-if-a-superclass-constructor-throws-an-exception) | 56 | | 39 | [How do exceptions work with polymorphism?](#how-do-exceptions-work-with-polymorphism) | 57 | | 40 | [What if a child class throws a checked exception not in the parent?](#what-if-a-child-class-throws-a-checked-exception-not-in-the-parent) | 58 | | 41 | [Can implementing classes throw checked exceptions not in the interface?](#can-implementing-classes-throw-checked-exceptions-not-in-the-interface) | 59 | | 42 | [What if an interface declares an exception the implementing class doesn't throw?](#what-if-an-interface-declares-an-exception-the-implementing-class-doesnt-throw) | 60 | | 43 | [How does exception handling work with abstract classes?](#how-does-exception-handling-work-with-abstract-classes) | 61 | | 44 | [How does exception handling work with multiple inheritance levels?](#how-does-exception-handling-work-with-multiple-inheritance-levels) | 62 | | 45 | [Can constructors throw exceptions in inheritance?](#can-constructors-throw-exceptions-in-inheritance) | 63 | | 46 | [How does exception handling work with covariant return types?](#how-does-exception-handling-work-with-covariant-return-types) | 64 | | 47 | [Can a subclass override with an unchecked exception?](#can-a-subclass-override-with-an-unchecked-exception) | 65 | | 48 | [Can a catch block handle a superclass exception?](#can-a-catch-block-handle-a-superclass-exception) | 66 | | 49 | [What happens with super() and exceptions?](#what-happens-with-super-and-exceptions) | 67 | -------------------------------------------------------------------------------- /exception-handling/notes-2.md: -------------------------------------------------------------------------------- 1 | # Java Exception Handling - Complete Notes 2 | 3 | ## OutOfMemoryError vs StackOverflowError 4 | 5 | ### OutOfMemoryError 6 | - **Type**: Error (not Exception) 7 | - **Cause**: JVM runs out of heap memory 8 | - **Common scenarios**: 9 | - Creating too many objects 10 | - Memory leaks 11 | - Large arrays or collections 12 | - **Example**: `String[] huge = new String[Integer.MAX_VALUE];` 13 | - **Recovery**: Usually fatal, difficult to recover from 14 | 15 | ### StackOverflowError 16 | - **Type**: Error (not Exception) 17 | - **Cause**: Call stack exceeds maximum depth 18 | - **Common scenarios**: 19 | - Infinite recursion 20 | - Very deep method calls 21 | - **Example**: Method calling itself without base condition 22 | - **Recovery**: Usually fatal, indicates programming error 23 | 24 | ```java 25 | // StackOverflowError example 26 | public void infiniteRecursion() { 27 | infiniteRecursion(); // No base case 28 | } 29 | ``` 30 | 31 | ## Exception Chaining 32 | 33 | **Definition**: Technique of catching one exception and throwing another while preserving the original exception information. 34 | 35 | **Purpose**: 36 | - Maintain exception history 37 | - Provide better context 38 | - Hide implementation details while preserving debugging info 39 | 40 | ```java 41 | try { 42 | // some operation 43 | } catch (IOException e) { 44 | throw new ServiceException("Service failed", e); // 'e' is the cause 45 | } 46 | 47 | // Accessing chained exceptions 48 | catch (ServiceException e) { 49 | Throwable cause = e.getCause(); // Gets original IOException 50 | } 51 | ``` 52 | 53 | **Key methods**: 54 | - `initCause(Throwable cause)` 55 | - `getCause()` 56 | 57 | ## ClassNotFoundException vs NoClassDefFoundError 58 | 59 | ### ClassNotFoundException 60 | - **Type**: Checked Exception 61 | - **When**: Runtime class loading fails 62 | - **Cause**: Class not found in classpath during `Class.forName()` or similar 63 | - **Example**: `Class.forName("com.example.MissingClass")` 64 | 65 | ### NoClassDefFoundError 66 | - **Type**: Error 67 | - **When**: Class was available at compile time but missing at runtime 68 | - **Cause**: Class present during compilation but removed/corrupted in runtime classpath 69 | - **Example**: Class A uses Class B, B was deleted after compilation 70 | 71 | ```java 72 | // ClassNotFoundException 73 | try { 74 | Class.forName("NonExistentClass"); 75 | } catch (ClassNotFoundException e) { 76 | // Handle gracefully 77 | } 78 | 79 | // NoClassDefFoundError - cannot be caught as easily 80 | // Usually indicates deployment/classpath issues 81 | ``` 82 | 83 | ## Try Block Without Catch/Finally 84 | 85 | **Question**: Can we use only try blocks without catch and finally? 86 | 87 | **Answer**: **NO** - This is a compilation error. 88 | 89 | **Valid combinations**: 90 | - `try-catch` 91 | - `try-finally` 92 | - `try-catch-finally` 93 | - `try-with-resources` (automatic resource management) 94 | 95 | ```java 96 | // INVALID - Compilation error 97 | try { 98 | // code 99 | } 100 | 101 | // VALID options 102 | try { 103 | // code 104 | } catch (Exception e) { 105 | // handle 106 | } 107 | 108 | try { 109 | // code 110 | } finally { 111 | // cleanup 112 | } 113 | 114 | // try-with-resources (valid) 115 | try (FileReader fr = new FileReader("file.txt")) { 116 | // code 117 | } // automatic resource closing 118 | ``` 119 | 120 | ## Empty Catch Block 121 | 122 | **Question**: Can we have an empty catch block? 123 | 124 | **Answer**: **YES** - Syntactically valid but **NOT RECOMMENDED**. 125 | 126 | ```java 127 | try { 128 | riskyOperation(); 129 | } catch (Exception e) { 130 | // Empty - compiles but poor practice 131 | } 132 | 133 | // Better approaches 134 | try { 135 | riskyOperation(); 136 | } catch (Exception e) { 137 | logger.error("Operation failed", e); 138 | // or at minimum: 139 | e.printStackTrace(); 140 | } 141 | ``` 142 | 143 | **Problems with empty catch**: 144 | - Silent failures 145 | - Difficult debugging 146 | - Masked errors 147 | 148 | ## Finally Block Execution 149 | 150 | **Question**: Does finally block always execute? 151 | 152 | **Answer**: **Almost always**, with exceptions. 153 | 154 | ### Finally ALWAYS executes when: 155 | - Normal execution 156 | - Exception thrown and caught 157 | - Exception thrown and not caught 158 | - Return statement in try/catch 159 | 160 | ### Finally DOES NOT execute when: 161 | - `System.exit()` called 162 | - JVM crashes 163 | - Infinite loop in try/catch 164 | - Thread interrupted/killed 165 | 166 | ```java 167 | try { 168 | System.exit(0); // Finally will NOT execute 169 | return "try"; 170 | } catch (Exception e) { 171 | System.exit(0); // Finally will NOT execute 172 | return "catch"; 173 | } finally { 174 | System.out.println("This won't print if System.exit() called"); 175 | } 176 | ``` 177 | 178 | ## System.exit(0) Impact 179 | 180 | **Effect**: Immediately terminates JVM, bypassing finally blocks. 181 | 182 | ```java 183 | try { 184 | System.out.println("Try block"); 185 | System.exit(0); // JVM terminates here 186 | } finally { 187 | System.out.println("Finally - WILL NOT EXECUTE"); 188 | } 189 | ``` 190 | 191 | **Note**: Only `System.exit()` prevents finally execution in normal circumstances. 192 | 193 | ## Checked Exceptions from Static Block 194 | 195 | **Question**: Can we throw checked exceptions from static blocks? 196 | 197 | **Answer**: **NO** - Static blocks cannot throw checked exceptions. 198 | 199 | ```java 200 | // INVALID - Compilation error 201 | static { 202 | throw new IOException(); // Checked exception not allowed 203 | } 204 | 205 | // VALID - Runtime exceptions allowed 206 | static { 207 | throw new RuntimeException(); // Unchecked exception OK 208 | } 209 | 210 | // WORKAROUND - Wrap in runtime exception 211 | static { 212 | try { 213 | // risky operation 214 | } catch (IOException e) { 215 | throw new ExceptionInInitializerError(e); 216 | } 217 | } 218 | ``` 219 | 220 | **Reason**: No method signature to declare throws clause for static blocks. 221 | 222 | ## Exception from Main Method 223 | 224 | **What happens**: Uncaught exceptions in main method terminate the program. 225 | 226 | ```java 227 | public static void main(String[] args) throws IOException { 228 | throw new IOException("Main method exception"); 229 | // Program terminates, stack trace printed to stderr 230 | } 231 | ``` 232 | 233 | **Process**: 234 | 1. Exception propagates up call stack 235 | 2. If uncaught, JVM's default exception handler takes over 236 | 3. Stack trace printed to System.err 237 | 4. Program terminates with non-zero exit code 238 | 239 | ## JVM Exception Handling 240 | 241 | **When exception occurs, JVM**: 242 | 1. Creates exception object 243 | 2. Looks for matching catch block in current method 244 | 3. If not found, propagates to calling method 245 | 4. Continues up call stack 246 | 5. If reaches top (main method) uncaught: 247 | - Prints stack trace 248 | - Terminates program 249 | 250 | **Default Exception Handler**: 251 | - Prints exception class name 252 | - Prints exception message 253 | - Prints stack trace 254 | - Terminates thread/program 255 | 256 | ## Stack Trace 257 | 258 | **Definition**: Detailed report showing the sequence of method calls leading to an exception. 259 | 260 | **Components**: 261 | - Exception class and message 262 | - Method names and line numbers 263 | - File names 264 | - Call sequence (most recent first) 265 | 266 | ```java 267 | Exception in thread "main" java.lang.NullPointerException: Cannot invoke method 268 | at com.example.MyClass.method3(MyClass.java:15) 269 | at com.example.MyClass.method2(MyClass.java:10) 270 | at com.example.MyClass.method1(MyClass.java:5) 271 | at com.example.MyClass.main(MyClass.java:3) 272 | ``` 273 | 274 | **Usage**: 275 | - Debugging 276 | - Error tracking 277 | - Understanding execution flow 278 | 279 | ## Runtime Exceptions 280 | 281 | **Definition**: Unchecked exceptions that extend `RuntimeException`. 282 | 283 | **Characteristics**: 284 | - **Not required** to be caught or declared 285 | - Usually indicate programming errors 286 | - Can occur anywhere in code 287 | - Checked at runtime, not compile time 288 | 289 | ### Common Runtime Exceptions: 290 | 291 | **NullPointerException** 292 | ```java 293 | String str = null; 294 | int length = str.length(); // NPE 295 | ``` 296 | 297 | **ArrayIndexOutOfBoundsException** 298 | ```java 299 | int[] arr = {1, 2, 3}; 300 | int value = arr[5]; // Index out of bounds 301 | ``` 302 | 303 | **IllegalArgumentException** 304 | ```java 305 | Thread.sleep(-1000); // Negative argument not allowed 306 | ``` 307 | 308 | **NumberFormatException** 309 | ```java 310 | int num = Integer.parseInt("abc"); // Invalid number format 311 | ``` 312 | 313 | **ClassCastException** 314 | ```java 315 | Object obj = "Hello"; 316 | Integer num = (Integer) obj; // Invalid cast 317 | ``` 318 | 319 | **ArithmeticException** 320 | ```java 321 | int result = 10 / 0; // Division by zero 322 | ``` 323 | 324 | ### Runtime vs Checked Exceptions: 325 | 326 | | Aspect | Runtime Exceptions | Checked Exceptions | 327 | |--------|-------------------|-------------------| 328 | | **Handling** | Optional | Mandatory | 329 | | **Compilation** | No compile-time check | Must catch or declare | 330 | | **Purpose** | Programming errors | Recoverable conditions | 331 | | **Examples** | NPE, IllegalArgument | IOException, SQLException | 332 | | **Base Class** | RuntimeException | Exception (not Runtime) | 333 | 334 | **Best Practice**: Handle runtime exceptions when you can recover, but don't catch them just to ignore them. -------------------------------------------------------------------------------- /exception-handling/notes-3.md: -------------------------------------------------------------------------------- 1 | 2 | ## What is Exception Suppression? 3 | 4 | Exception suppression is a feature introduced in Java 7, primarily to handle exceptions that occur when **closing resources** in a **try-with-resources** block. 5 | 6 | --- 7 | 8 | ## Why is it needed? 9 | 10 | Imagine this scenario without try-with-resources: 11 | 12 | ```java 13 | InputStream in = null; 14 | try { 15 | in = new FileInputStream("file.txt"); 16 | // Read from the file, some exception occurs here 17 | } catch (IOException e) { 18 | // handle exception from try block 19 | } finally { 20 | if (in != null) { 21 | try { 22 | in.close(); // close might throw IOException too 23 | } catch (IOException e) { 24 | // What do you do here? The close() throws an exception 25 | } 26 | } 27 | } 28 | ``` 29 | 30 | * If an exception is thrown in the **try block** (e.g., while reading the file), and then `close()` in the finally block **also throws an exception**, the exception from `close()` would normally **overwrite** or **hide** the original exception from the try block. 31 | 32 | * This means the original exception (which is often the *root cause*) is lost. 33 | 34 | --- 35 | 36 | ## How does try-with-resources solve this? 37 | 38 | ```java 39 | try (InputStream in = new FileInputStream("file.txt")) { 40 | // use resource 41 | // if an exception occurs here, this is the primary exception 42 | } 43 | // resource is automatically closed here 44 | ``` 45 | 46 | * When the resource is closed automatically at the end of the try-with-resources, **if an exception is thrown during the try block, and then an exception is thrown again during closing the resource**, Java **suppresses** the exception thrown by the close() method. 47 | 48 | * The **primary exception** is the one thrown inside the try block (the main operation). 49 | 50 | * The exception thrown by the `close()` method is **suppressed**, but **not lost**. It is stored as a **suppressed exception** inside the primary exception. 51 | 52 | --- 53 | 54 | ## How to access suppressed exceptions? 55 | 56 | Java provides a method on `Throwable`: 57 | 58 | ```java 59 | Throwable.getSuppressed() 60 | ``` 61 | 62 | This method returns an array of suppressed exceptions, so you can inspect all exceptions that were suppressed during the closing of resources. 63 | 64 | --- 65 | 66 | ## Detailed Example 67 | 68 | ```java 69 | class Resource implements AutoCloseable { 70 | @Override 71 | public void close() throws Exception { 72 | throw new Exception("Exception from close()"); 73 | } 74 | 75 | public void doSomething() throws Exception { 76 | throw new Exception("Exception from doSomething()"); 77 | } 78 | } 79 | 80 | public class TestSuppressed { 81 | public static void main(String[] args) { 82 | try (Resource r = new Resource()) { 83 | r.doSomething(); // throws exception 84 | } catch (Exception e) { 85 | System.out.println("Primary Exception: " + e.getMessage()); 86 | 87 | Throwable[] suppressed = e.getSuppressed(); 88 | for (Throwable sup : suppressed) { 89 | System.out.println("Suppressed Exception: " + sup.getMessage()); 90 | } 91 | } 92 | } 93 | } 94 | ``` 95 | 96 | **Output:** 97 | 98 | ``` 99 | Primary Exception: Exception from doSomething() 100 | Suppressed Exception: Exception from close() 101 | ``` 102 | 103 | * The **exception from `doSomething()`** is the primary exception thrown. 104 | * The **exception from `close()`** is suppressed but accessible through `getSuppressed()`. 105 | 106 | --- 107 | 108 | ## Summary: 109 | 110 | | Concept | Explanation | 111 | | --------------------------- | ------------------------------------------------------------------------------------------------ | 112 | | Primary Exception | The exception thrown inside the `try` block (main operation exception). | 113 | | Suppressed Exception | Exceptions thrown while closing the resources in try-with-resources are suppressed. | 114 | | Exception hiding problem | Without suppression, close() exceptions would overwrite or hide the primary exception. | 115 | | Accessing suppressed errors | Via `Throwable.getSuppressed()` method you can retrieve suppressed exceptions for logging/debug. | 116 | 117 | --- 118 | 119 | If you want, I can also show how this works in traditional try-finally blocks or how you can manually add suppressed exceptions using `Throwable.addSuppressed()`. Would you like that? 120 | 121 | 122 | 123 |














124 | -------------------------------------------------------------------------------- /exception-handling/notes-4-varous-exceptions.md: -------------------------------------------------------------------------------- 1 | ``` 2 | what are the various types of excptioins can be raised wkg with the ________ . 3 | 1.how to handle . 4 | 2.how to prevent not to raise 5 | 6 | restful api, 7 | multhi threaded env, 8 | executr service, 9 | spring secutiy, 10 | spring cloud microservices , 11 | down stream is throwing an exceptions, 12 | apache kafka 13 | 14 | wkg with files & IO, 15 | jvm memeroy managment 16 | 17 | few coding questions are there. 18 | https://www.digitalocean.com/community/tutorials/java-exception-interview-questions-and-answers 19 | 20 | ``` 21 | 22 | ## ✅ What is a `RuntimeException`? 23 | 24 | * A `RuntimeException` is an **unchecked exception**, meaning the compiler does **not require** it to be caught or declared. 25 | * It usually indicates **programming errors**, such as logic bugs or improper use of APIs. 26 | 27 | --- 28 | 29 | ## ⚠️ Common `RuntimeException` Types with Causes and Prevention 30 | 31 | ### 1. **`NullPointerException`** 32 | 33 | * **Reason:** Accessing an object or method on a null reference. 34 | * **Example:** 35 | 36 | ```java 37 | String s = null; 38 | s.length(); // Throws NullPointerException 39 | ``` 40 | * **Prevention:** 41 | 42 | * Always check for `null` before accessing objects. 43 | * Use `Optional` to handle possible nulls. 44 | * Use `Objects.requireNonNull(obj)` to fail fast. 45 | 46 | --- 47 | 48 | ### 2. **`ArrayIndexOutOfBoundsException`** 49 | 50 | * **Reason:** Trying to access an array with an illegal index (either negative or >= array length). 51 | * **Example:** 52 | 53 | ```java 54 | int[] arr = new int[3]; 55 | int val = arr[5]; // Index 5 is out of bounds 56 | ``` 57 | * **Prevention:** 58 | 59 | * Use `arr.length` to check bounds before accessing. 60 | * Use enhanced for-loop or `Arrays.stream()` for iteration. 61 | 62 | --- 63 | 64 | ### 3. **`StringIndexOutOfBoundsException`** 65 | 66 | * **Reason:** Invalid string index access. 67 | * **Example:** 68 | 69 | ```java 70 | String s = "Java"; 71 | char c = s.charAt(10); // Index 10 is invalid 72 | ``` 73 | * **Prevention:** 74 | 75 | * Always validate index using `s.length()` before using `charAt()` or `substring()`. 76 | 77 | --- 78 | 79 | ### 4. **`ClassCastException`** 80 | 81 | * **Reason:** Incorrect casting between incompatible types. 82 | * **Example:** 83 | 84 | ```java 85 | Object obj = "Java"; 86 | Integer i = (Integer) obj; // String can't be cast to Integer 87 | ``` 88 | * **Prevention:** 89 | 90 | * Use `instanceof` before casting. 91 | * Favor generics to avoid type mismatches. 92 | 93 | --- 94 | 95 | ### 5. **`IllegalArgumentException`** 96 | 97 | * **Reason:** Passing invalid arguments to a method. 98 | * **Example:** 99 | 100 | ```java 101 | Thread.sleep(-1000); // Negative sleep time 102 | ``` 103 | * **Prevention:** 104 | 105 | * Validate method parameters before using them. 106 | * Use assertions or custom validation logic. 107 | 108 | --- 109 | 110 | ### 6. **`IllegalStateException`** 111 | 112 | * **Reason:** Calling a method at an inappropriate time or in the wrong state. 113 | * **Example:** 114 | 115 | ```java 116 | Iterator it = list.iterator(); 117 | it.remove(); // IllegalStateException if next() not called first 118 | ``` 119 | * **Prevention:** 120 | 121 | * Ensure proper state transitions before calling methods. 122 | * Use `state` flags to manage the flow. 123 | 124 | --- 125 | 126 | ### 7. **`NumberFormatException`** 127 | 128 | * **Reason:** Converting a malformed string into a number. 129 | * **Example:** 130 | 131 | ```java 132 | int num = Integer.parseInt("abc"); // Cannot parse "abc" 133 | ``` 134 | * **Prevention:** 135 | 136 | * Validate the string using regex or try-catch before parsing. 137 | * Use `tryParse()` pattern or exception handling. 138 | 139 | --- 140 | 141 | ### 8. **`ArithmeticException`** 142 | 143 | * **Reason:** Performing illegal math operations (e.g., divide by zero). 144 | * **Example:** 145 | 146 | ```java 147 | int a = 10 / 0; // Division by zero 148 | ``` 149 | * **Prevention:** 150 | 151 | * Always check for divisor being zero before dividing. 152 | 153 | --- 154 | 155 | ### 9. **`UnsupportedOperationException`** 156 | 157 | * **Reason:** Invoking an operation that's not supported. 158 | * **Example:** 159 | 160 | ```java 161 | List list = Arrays.asList("a", "b"); 162 | list.add("c"); // Fixed-size list throws this exception 163 | ``` 164 | * **Prevention:** 165 | 166 | * Check if collection is modifiable before altering. 167 | * Use appropriate collection types. 168 | 169 | --- 170 | 171 | ### 10. **`ConcurrentModificationException`** 172 | 173 | * **Reason:** Modifying a collection while iterating over it using a standard loop. 174 | * **Example:** 175 | 176 | ```java 177 | for (String s : list) { 178 | list.remove(s); // Concurrent modification 179 | } 180 | ``` 181 | * **Prevention:** 182 | 183 | * Use `Iterator.remove()` during iteration. 184 | * Use concurrent collections like `CopyOnWriteArrayList`. 185 | 186 | --- 187 | 188 | ### 11. **`NegativeArraySizeException`** 189 | 190 | * **Reason:** Trying to create an array with a negative size. 191 | * **Example:** 192 | 193 | ```java 194 | int[] arr = new int[-5]; // Negative size 195 | ``` 196 | * **Prevention:** 197 | 198 | * Validate the array size before allocation. 199 | * Ensure the input is non-negative using an `if` condition. 200 | 201 | --- 202 | 203 | ### 12. **`IndexOutOfBoundsException`** 204 | 205 | * **Reason:** Trying to access a list or array with an invalid index. 206 | * **Example:** 207 | 208 | ```java 209 | List list = new ArrayList<>(); 210 | list.get(2); // List is empty 211 | ``` 212 | * **Prevention:** 213 | 214 | * Always check `list.size()` or `array.length` before accessing by index. 215 | 216 | --- 217 | 218 | ### 13. **`NoSuchElementException`** 219 | 220 | * **Reason:** Accessing an element that doesn't exist, like calling `next()` on an empty iterator. 221 | * **Example:** 222 | 223 | ```java 224 | Iterator it = new ArrayList().iterator(); 225 | it.next(); // No element to return 226 | ``` 227 | * **Prevention:** 228 | 229 | * Always check `iterator.hasNext()` before calling `next()`. 230 | 231 | --- 232 | 233 | ### 14. **`EmptyStackException`** 234 | 235 | * **Reason:** Popping or peeking from an empty stack. 236 | * **Example:** 237 | 238 | ```java 239 | Stack stack = new Stack<>(); 240 | stack.pop(); // Empty stack 241 | ``` 242 | * **Prevention:** 243 | 244 | * Check `stack.isEmpty()` before calling `pop()` or `peek()`. 245 | 246 | --- 247 | 248 | 249 | ## ✅ General Prevention Techniques 250 | 251 | | Strategy | Description | 252 | | ------------------------------ | ---------------------------------------------------------- | 253 | | Input validation | Always validate inputs to methods. | 254 | | Null checks / Optional | Avoid `null` references; use `Optional` where appropriate. | 255 | | Use enhanced for-loops | Safer for iterating collections. | 256 | | Exception handling (try-catch) | Handle parsing or risky operations gracefully. | 257 | | Defensive programming | Code to handle incorrect usage or states. | 258 | | Proper API usage | Follow the method contracts and expected usage. | 259 | | Use static code analysis tools | Tools like SonarLint, FindBugs can identify risky code. | 260 | 261 | --- 262 | 263 | Would you like this in a **PDF format**, **cheat sheet**, or **flashcards** style for easier revision? 264 | 265 | 266 |




267 | 268 | Here's a comprehensive note on **various types of exceptions in a multithreaded environment**, along with their **causes, examples, prevention techniques**, and what **caution to take**: 269 | 270 | --- 271 | 272 | ## 🧵 Multithreaded Environment: Types of Exceptions & Precautions 273 | 274 | ### 🔹 1. `InterruptedException` 275 | 276 | **Cause**: 277 | Thrown when a thread is waiting, sleeping, or otherwise occupied and another thread interrupts it using `thread.interrupt()`. 278 | 279 | **Example**: 280 | 281 | ```java 282 | Thread.sleep(1000); // may throw InterruptedException 283 | ``` 284 | 285 | **Prevention / Handling**: 286 | 287 | * Always handle using `try-catch`. 288 | * Restore the interrupt status if not processing immediately: 289 | 290 | ```java 291 | catch (InterruptedException e) { 292 | Thread.currentThread().interrupt(); // preserve interrupt status 293 | } 294 | ``` 295 | 296 | **Caution**: Ignoring this can result in threads not responding to cancellation requests. 297 | 298 | --- 299 | 300 | ### 🔹 2. `IllegalThreadStateException` 301 | 302 | **Cause**: 303 | Occurs when an operation is not allowed in the current thread state (e.g., starting a thread that's already started). 304 | 305 | **Example**: 306 | 307 | ```java 308 | Thread t = new Thread(); 309 | t.start(); 310 | t.start(); // throws IllegalThreadStateException 311 | ``` 312 | 313 | **Prevention**: 314 | 315 | * Ensure a thread is started only once. 316 | * Use thread state (`Thread.State`) to check status before actions. 317 | 318 | **Caution**: This is a programming logic error, should be caught during development. 319 | 320 | --- 321 | 322 | ### 🔹 3. `ConcurrentModificationException` 323 | 324 | **Cause**: 325 | Thrown when a collection is modified concurrently while iterating over it. 326 | 327 | **Example**: 328 | 329 | ```java 330 | List list = new ArrayList<>(); 331 | for (String s : list) { 332 | list.remove(s); // unsafe 333 | } 334 | ``` 335 | 336 | **Prevention**: 337 | 338 | * Use `CopyOnWriteArrayList`, `ConcurrentHashMap`, etc. 339 | * Or use `Iterator.remove()` safely within iteration. 340 | 341 | **Caution**: Avoid modifying shared collections without synchronization. 342 | 343 | --- 344 | 345 | ### 🔹 4. `ExecutionException` 346 | 347 | **Cause**: 348 | Thrown by `Future.get()` when a task throws an exception during execution in a thread pool. 349 | 350 | **Example**: 351 | 352 | ```java 353 | Future result = executor.submit(() -> 1 / 0); 354 | result.get(); // throws ExecutionException 355 | ``` 356 | 357 | **Prevention**: 358 | 359 | * Always wrap `get()` in `try-catch`. 360 | * Analyze root cause via `e.getCause()`. 361 | 362 | --- 363 | 364 | ### 🔹 5. `RejectedExecutionException` 365 | 366 | **Cause**: 367 | When a task is submitted to an executor that has been shut down or whose queue is full. 368 | 369 | **Example**: 370 | 371 | ```java 372 | executor.shutdown(); 373 | executor.submit(() -> doSomething()); // throws RejectedExecutionException 374 | ``` 375 | 376 | **Prevention**: 377 | 378 | * Check if executor is active before submitting. 379 | * Use proper thread pool sizing and queue management. 380 | 381 | --- 382 | 383 | ### 🔹 6. `Deadlock` (not an exception, but a critical issue) 384 | 385 | **Cause**: 386 | Two or more threads waiting indefinitely for resources locked by each other. 387 | 388 | **Example**: 389 | 390 | ```java 391 | synchronized(lock1) { 392 | synchronized(lock2) { 393 | // ... 394 | } 395 | } 396 | ``` 397 | 398 | **Prevention**: 399 | 400 | * Avoid nested locking. 401 | * Always lock resources in a consistent global order. 402 | * Use try-lock with timeout (`ReentrantLock.tryLock()`). 403 | 404 | **Caution**: Deadlocks do not throw exceptions but freeze part of your program. 405 | 406 | --- 407 | 408 | ### 🔹 7. `Race Conditions` 409 | 410 | **Cause**: 411 | Two threads modifying shared data without proper synchronization, leading to inconsistent or incorrect results. 412 | 413 | **Example**: 414 | 415 | ```java 416 | counter++; // not atomic 417 | ``` 418 | 419 | **Prevention**: 420 | 421 | * Use `synchronized`, `volatile`, or `AtomicInteger`/`LongAdder`. 422 | 423 | --- 424 | 425 | ### 🔹 8. `ThreadDeath` (rare and discouraged) 426 | 427 | **Cause**: 428 | When `Thread.stop()` is called. It throws `ThreadDeath` which is a subclass of `Error`. 429 | 430 | **Prevention**: 431 | 432 | * **Avoid using** `stop()`, `suspend()`, `resume()` – these are deprecated and unsafe. 433 | * Use interrupt mechanism and cooperative stopping. 434 | 435 | --- 436 | 437 | ## 🛡️ Best Practices to Prevent Disruption 438 | 439 | 1. **Graceful Shutdown**: Use `shutdown()` and `awaitTermination()` in `ExecutorService`. 440 | 2. **Thread Safety**: Use concurrent data structures or proper locking. 441 | 3. **Atomic Operations**: Use `Atomic*` classes for counters and flags. 442 | 4. **Exception Handling in Threads**: 443 | 444 | * Use `Thread.setUncaughtExceptionHandler(...)` to catch exceptions in threads. 445 | * For executor tasks, wrap runnables with try-catch blocks. 446 | 5. **Avoid Blocking Calls Without Timeouts**. 447 | 6. **Use Thread-safe Libraries (java.util.concurrent)**. 448 | 449 | --- 450 | 451 | ## ⚠️ Key Cautions 452 | 453 | * **Always handle `InterruptedException` properly**. 454 | * **Never use deprecated thread control methods**. 455 | * **Avoid shared mutable state unless synchronized**. 456 | * **Monitor for deadlocks** using tools like `jconsole`, `jstack`. 457 | * **Always analyze stack trace when exceptions occur in a thread pool**. 458 | 459 | --- 460 | 461 | If you want this in a downloadable PDF format or want the same for a specific language or framework (like Spring Boot multithreading), let me know! 462 | 463 | 464 |







465 | 466 | ## 🔍 When You Call `Future.get()`, What Exceptions Can Be Thrown? 467 | 468 | ### ✅ Signature: 469 | 470 | ```java 471 | V get() throws InterruptedException, ExecutionException; 472 | ``` 473 | 474 | ### ✅ So, `.get()` may throw: 475 | 476 | 1. **`InterruptedException`** 477 | 478 | * If the current thread was interrupted while waiting. 479 | 2. **`ExecutionException`** 480 | 481 | * If the task inside the `Future` threw an exception during execution. 482 | 483 | ### ✅ `ExecutionException.getCause()` returns the actual root cause. 484 | 485 | This can be: 486 | 487 | * `RuntimeException` (e.g., `NullPointerException`, `IllegalArgumentException`, etc.) 488 | * `CheckedException` (e.g., `IOException`, `SQLException`, etc.) 489 | * `Error` (e.g., `OutOfMemoryError`, but this is rare and usually not caught) 490 | 491 | ### So your code should look like: 492 | 493 | ```java 494 | Future result = loadDataFromDb(); 495 | 496 | try { 497 | Integer value = result.get(); // blocking call 498 | } catch (InterruptedException e) { 499 | // Handle thread interruption - usually restore interrupt status 500 | Thread.currentThread().interrupt(); 501 | System.out.println("Thread was interrupted"); 502 | } catch (ExecutionException e) { // ExecutionException is a checked exception 503 | Throwable cause = e.getCause(); // Root cause of failure in the Callable 504 | 505 | if (cause instanceof NullPointerException) { // NullPointerException is an unchecked exception 506 | System.out.println("NPE occurred: " + cause.getMessage()); 507 | } else if (cause instanceof SQLException) { 508 | System.out.println("Database error: " + cause.getMessage()); 509 | } else { 510 | System.out.println("Unexpected error: " + cause); 511 | } 512 | } 513 | ``` 514 | 515 | ### 🔹 Why `SQLException` is important to handle? 516 | 517 | * It’s a **checked exception**, and commonly occurs when: 518 | 519 | * DB connection fails 520 | * Query is malformed 521 | * Timeout happens 522 | * Data integrity issues 523 | 524 | --- 525 | 526 | ## 🎯 Best Practices 527 | 528 | * **Always distinguish between `InterruptedException` and `ExecutionException`**. 529 | * **Log or inspect `e.getCause()` from `ExecutionException` to handle real root cause.** 530 | * Optionally, **wrap exceptions in your own custom exception** to provide consistent error handling in your service/method. 531 | 532 | --- 533 | 534 | ## ✅ Summary 535 | 536 | When calling `.get()` on a `Future`: 537 | 538 | * Always handle both `InterruptedException` and `ExecutionException`. 539 | * Dig into `ExecutionException.getCause()` to find the actual exception. 540 | * Be cautious of blocking behavior of `.get()` — prefer `get(timeout, unit)` if timeouts are important. 541 | --- 542 |









543 | 544 | When working with **ExecutorService** in Java, several exceptions can arise — some due to how the executor itself is used, and others due to the tasks running inside it. 545 | 546 | Here's a breakdown of the **most common exceptions** and how to **handle or prevent** them effectively. 547 | 548 | --- 549 | 550 | ## ✅ Most Common Exceptions with `ExecutorService` 551 | 552 | ### 1. **`RejectedExecutionException`** 553 | 554 | **Cause**: Task is submitted after the executor is shut down, or the task queue is full (in bounded executors). 555 | 556 | **When**: 557 | 558 | ```java 559 | executor.shutdown(); 560 | executor.submit(task); // throws RejectedExecutionException 561 | ``` 562 | 563 | **Prevention**: 564 | 565 | * Check `executor.isShutdown()` or `isTerminated()` before submitting. 566 | * Use a `CallerRunsPolicy` or another rejection handler in `ThreadPoolExecutor`. 567 | 568 | --- 569 | 570 | ### 2. **`InterruptedException`** 571 | 572 | **Cause**: 573 | 574 | * The current thread was interrupted while waiting (e.g., in `get()`, `awaitTermination()`). 575 | * Happens during shutdown or task blocking. 576 | 577 | **Where**: 578 | 579 | ```java 580 | executor.awaitTermination(10, TimeUnit.SECONDS); 581 | future.get(); // may throw InterruptedException 582 | ``` 583 | 584 | **Handling**: 585 | 586 | ```java 587 | catch (InterruptedException e) { 588 | Thread.currentThread().interrupt(); // Restore interrupted status 589 | // Handle cleanup or retry 590 | } 591 | ``` 592 | 593 | --- 594 | 595 | ### 3. **`ExecutionException`** 596 | 597 | **Cause**: The task submitted to the executor threw an exception internally. 598 | 599 | **Where**: 600 | 601 | ```java 602 | Future result = executor.submit(() -> { 603 | throw new NullPointerException(); 604 | }); 605 | result.get(); // throws ExecutionException 606 | ``` 607 | 608 | **Handling**: 609 | 610 | ```java 611 | catch (ExecutionException e) { 612 | Throwable cause = e.getCause(); // Root cause 613 | if (cause instanceof NullPointerException) { ... } 614 | } 615 | ``` 616 | 617 | --- 618 | 619 | ### 4. **`TimeoutException`** 620 | 621 | **Cause**: 622 | 623 | * `.get(timeout, unit)` on a `Future` did not complete in time. 624 | 625 | **Where**: 626 | 627 | ```java 628 | future.get(2, TimeUnit.SECONDS); // throws TimeoutException 629 | ``` 630 | 631 | **Prevention**: 632 | 633 | * Monitor long-running tasks. 634 | * Use proper timeout values. 635 | 636 | --- 637 | 638 | ### 5. **`IllegalArgumentException` / `NullPointerException`** 639 | 640 | **Cause**: You passed invalid arguments or nulls to `submit()`, `schedule()`, or `invokeAll()`. 641 | 642 | **Example**: 643 | 644 | ```java 645 | executor.submit(null); // NPE 646 | executor.schedule(() -> {}, -1, TimeUnit.SECONDS); // IllegalArgumentException 647 | ``` 648 | 649 | --- 650 | 651 | ### 6. **`CancellationException`** 652 | 653 | **Cause**: You call `get()` on a task that was cancelled using `future.cancel()`. 654 | 655 | **Where**: 656 | 657 | ```java 658 | future.cancel(true); 659 | future.get(); // throws CancellationException 660 | ``` 661 | 662 | --- 663 | 664 | ### 7. **`ClassCastException` / `ClassNotFoundException`** 665 | 666 | **Cause**: Often occur when using custom thread factories or deserializing objects in distributed executors. 667 | 668 | (Not frequent in typical usage, but worth noting in advanced setups.) 669 | 670 | --- 671 | 672 | ## 🧠 Summary Table 673 | 674 | | Exception | When It Happens | How to Handle | 675 | | ---------------------------- | ----------------------------------------------- | ------------------------------------------------------------ | 676 | | `RejectedExecutionException` | Submitting after shutdown or queue full | Avoid submitting after shutdown; configure rejection handler | 677 | | `InterruptedException` | Blocking ops like `get()`, `awaitTermination()` | Restore interrupt status, clean up | 678 | | `ExecutionException` | Task throws exception internally | Inspect with `getCause()` | 679 | | `TimeoutException` | Task doesn't complete in time | Increase timeout, monitor execution | 680 | | `CancellationException` | Calling `get()` after cancel | Check `isCancelled()` before `get()` | 681 | | `NullPointerException` | Passing null task | Validate inputs | 682 | | `IllegalArgumentException` | Invalid delay/time/parameters | Validate parameters | 683 | 684 | --- 685 | 686 | ## ✅ Best Practices 687 | 688 | 1. **Always wrap `future.get()` in a `try-catch` block**. 689 | 2. **Use timeouts** with `get()` to avoid indefinite blocking. 690 | 3. **Design rejection policies** when using custom `ThreadPoolExecutor`. 691 | 4. **Handle `InterruptedException` properly** — don’t swallow it! 692 | 5. **Gracefully shut down** the executor using: 693 | 694 | ```java 695 | executor.shutdown(); 696 | executor.awaitTermination(timeout, unit); 697 | ``` 698 | 699 | --- 700 | 701 | Let me know if you want a checklist or reusable utility for safely handling tasks with `ExecutorService`. 702 | -------------------------------------------------------------------------------- /executor-service/ruf.txt: -------------------------------------------------------------------------------- 1 | 2 | look for refeatomic 3 | https://chatgpt.com/share/6832bbf2-2e38-8011-a6f4-a5108111cd15 -------------------------------------------------------------------------------- /executor-service/scenario-0.md: -------------------------------------------------------------------------------- 1 | # Asynchronous API Aggregation - Study Notes 2 | 3 | ## Problem Overview 4 | Combine data from multiple APIs asynchronously to create a unified customer profile while handling failures gracefully. 5 | 6 | ## Solution Approaches 7 | 8 | ### Approach 1: CompletableFuture with thenCombine() 9 | **How it works:** 10 | - Creates separate CompletableFuture for each API call 11 | - Uses `thenCombine()` to merge results step by step 12 | - Each future has error handling with `exceptionally()` 13 | - Returns default values when APIs fail 14 | ```java 15 | public static CustomerInfo getCombinedCustomerInfo() throws ExecutionException, InterruptedException { 16 | CompletableFuture personalFuture = CompletableFuture.supplyAsync(() -> 17 | CustomerService.getCustomerPersonalInfo()) 18 | .exceptionally(ex -> { 19 | System.out.println("Personal Info API failed: " + ex.getMessage()); 20 | return new CustomerPersonalInfo("N/A", "N/A"); 21 | }); 22 | 23 | CompletableFuture creditFuture = CompletableFuture.supplyAsync(() -> 24 | CustomerService.getCustomerCreditCardInfo()) 25 | .exceptionally(ex -> { 26 | System.out.println("Credit Card Info API failed: " + ex.getMessage()); 27 | return new CustomerCreditCardInfo("N/A", "N/A"); 28 | }); 29 | 30 | CompletableFuture transactionFuture = CompletableFuture.supplyAsync(() -> 31 | CustomerService.getCustomerTransactionInfo()) 32 | .exceptionally(ex -> { 33 | System.out.println("Transaction Info API failed: " + ex.getMessage()); 34 | return new CustomerTransactionInfo(0.0, "N/A"); 35 | }); 36 | 37 | return personalFuture.thenCombine(creditFuture, (personal, credit) -> 38 | new Object[] { personal, credit } 39 | ).thenCombine(transactionFuture, (array, transaction) -> 40 | new CustomerInfo( 41 | (CustomerPersonalInfo) array[0], 42 | (CustomerCreditCardInfo) array[1], 43 | transaction 44 | ) 45 | ).get(); 46 | } 47 | ``` 48 | **Pros:** 49 | - All API calls execute in parallel 50 | - Graceful error handling per API 51 | - Clean chaining syntax 52 | - Result available as single object 53 | 54 | **Cons:** 55 | - Complex nested combining logic 56 | - Object array casting required 57 | - Harder to extend for more APIs 58 | 59 | ### Approach 2: CompletableFuture with thenAccept() 60 | **How it works:** 61 | - Creates shared mutable object 62 | - Each API result directly updates the shared object 63 | - Uses `thenAccept()` to perform side effects 64 | - Parallel execution with shared state modification 65 | ```java 66 | // approach-2 for simillar kind of behavour as above. 67 | CompletableFuture nameFuture = CompletableFuture.supplyAsync(() -> getNameFromApi1()) 68 | .exceptionally(ex -> { 69 | System.out.println("API1 failed: " + ex.getMessage()); 70 | return "Unknown"; 71 | }) 72 | .thenAccept(customerInfo::setName); // safely set name 73 | 74 | CompletableFuture creditCardFuture = CompletableFuture.supplyAsync(() -> getCardFromApi2()) 75 | .exceptionally(ex -> { 76 | System.out.println("API2 failed: " + ex.getMessage()); 77 | return new CreditCardInfo("0000", "Default"); 78 | }) 79 | .thenAccept(customerInfo::setCreditCardInfo); // safely set credit card info 80 | ``` 81 | **Pros:** 82 | - Simpler syntax for multiple APIs 83 | - Direct object mutation 84 | - Easy to add more API calls 85 | 86 | **Cons:** 87 | - Requires mutable shared object 88 | - Thread safety concerns 89 | - Side effects make testing harder 90 | - No clear completion signal for all operations 91 | 92 | ## Better Alternative: CompletableFuture.allOf() 93 | 94 | ### Approach 3: Using allOf() (Recommended) 95 | ```java 96 | public static CustomerInfo getCombinedCustomerInfo() { 97 | CompletableFuture personalFuture = 98 | CompletableFuture.supplyAsync(() -> CustomerService.getCustomerPersonalInfo()) 99 | .exceptionally(ex -> new CustomerPersonalInfo("N/A", "N/A")); 100 | 101 | CompletableFuture creditFuture = 102 | CompletableFuture.supplyAsync(() -> CustomerService.getCustomerCreditCardInfo()) 103 | .exceptionally(ex -> new CustomerCreditCardInfo("N/A", "N/A")); 104 | 105 | CompletableFuture transactionFuture = 106 | CompletableFuture.supplyAsync(() -> CustomerService.getCustomerTransactionInfo()) 107 | .exceptionally(ex -> new CustomerTransactionInfo(0.0, "N/A")); 108 | 109 | return CompletableFuture.allOf(personalFuture, creditFuture, transactionFuture) 110 | .thenApply(v -> new CustomerInfo( 111 | personalFuture.join(), 112 | creditFuture.join(), 113 | transactionFuture.join() 114 | )).join(); 115 | } 116 | ``` 117 | 118 | **Why it's better:** 119 | - Cleaner and more readable 120 | - Easier to extend for more APIs 121 | - Clear completion semantics 122 | - No complex chaining or casting 123 | 124 | ## Key Concepts 125 | - **Parallel Execution:** All API calls run simultaneously 126 | - **Error Isolation:** Each API failure is handled independently 127 | - **Default Values:** Fallback data when services are unavailable 128 | - **Non-blocking:** Main thread isn't blocked during API calls 129 | 130 | ## Real-World Practice Scenarios 131 | 132 | ### Scenario 1: E-commerce Product Page 133 | **Problem:** Load product details from multiple services 134 | - **API 1:** Product basic info (name, description) 135 | - **API 2:** Pricing and discounts 136 | - **API 3:** Inventory status 137 | - **API 4:** Customer reviews summary 138 | - **Challenge:** Page should load even if some services are down 139 | 140 | ### Scenario 2: Social Media Dashboard 141 | **Problem:** Aggregate user's social media activity 142 | - **API 1:** Twitter posts and metrics 143 | - **API 2:** LinkedIn connections and updates 144 | - **API 3:** Instagram photos and engagement 145 | - **API 4:** Facebook posts and reactions 146 | - **Challenge:** Show available data, hide unavailable sections 147 | 148 | ### Scenario 3: Financial Portfolio Dashboard 149 | **Problem:** Build investment portfolio overview 150 | - **API 1:** Stock prices from market data provider 151 | - **API 2:** Account balances from bank 152 | - **API 3:** Cryptocurrency holdings 153 | - **API 4:** News and market analysis 154 | - **Challenge:** Real-time updates with different API response times 155 | 156 | ### Scenario 4: Travel Booking System 157 | **Problem:** Show comprehensive trip options 158 | - **API 1:** Flight availability and prices 159 | - **API 2:** Hotel room availability 160 | - **API 3:** Car rental options 161 | - **API 4:** Weather forecast for destination 162 | - **Challenge:** Timeout handling for slow travel APIs 163 | 164 | ### Scenario 5: Healthcare Patient Portal 165 | **Problem:** Patient medical summary dashboard 166 | - **API 1:** Basic patient demographics 167 | - **API 2:** Recent lab results 168 | - **API 3:** Prescription history 169 | - **API 4:** Upcoming appointments 170 | - **Challenge:** HIPAA compliance and secure error handling 171 | 172 | ## Best Practices 173 | 1. **Always handle exceptions** with `exceptionally()` 174 | 2. **Use meaningful default values** for failed API calls 175 | 3. **Set appropriate timeouts** for API calls 176 | 4. **Consider using Circuit Breaker pattern** for frequently failing services 177 | 5. **Log failures** for monitoring and debugging 178 | 6. **Use thread pools** for better resource management 179 | 180 | ## When to Use Each Approach 181 | - **Use allOf()** for 3+ independent API calls 182 | - **Use thenCombine()** for 2 APIs with simple combination logic 183 | - **Avoid thenAccept() approach** due to thread safety concerns -------------------------------------------------------------------------------- /executor-service/scenario-1.md: -------------------------------------------------------------------------------- 1 | # CompletableFuture Guide: E-Commerce Order Processing 2 | 3 | ## Problem Overview 4 | 5 | In e-commerce applications, order processing involves multiple independent tasks that can benefit from parallel execution: 6 | 7 | - **Order Validation**: Verify order details and business rules 8 | - **Payment Processing**: Handle payment gateway transactions 9 | - **Inventory Updates**: Adjust stock levels and availability 10 | - **Email Notifications**: Send confirmation emails to customers 11 | 12 | The challenge is orchestrating these tasks to run concurrently while ensuring all complete successfully before finalizing the order. 13 | 14 | ## Solution Approaches 15 | 16 | ### Approach 1: Parallel Execution with allOf() (Recommended) 17 | 18 | This approach runs all tasks in parallel and waits for completion using `CompletableFuture.allOf()`. 19 | 20 | ```java 21 | public class OrderProcessor { 22 | private final ExecutorService executor = Executors.newFixedThreadPool(4); 23 | 24 | public void processOrder(Order order) { 25 | CompletableFuture validation = CompletableFuture 26 | .runAsync(() -> validateOrder(order), executor); 27 | 28 | CompletableFuture payment = CompletableFuture 29 | .runAsync(() -> processPayment(order), executor); 30 | 31 | CompletableFuture inventory = CompletableFuture 32 | .runAsync(() -> updateInventory(order), executor); 33 | 34 | CompletableFuture notification = CompletableFuture 35 | .runAsync(() -> sendConfirmationEmail(order), executor); 36 | 37 | CompletableFuture allTasks = CompletableFuture.allOf( 38 | validation, payment, inventory, notification 39 | ); 40 | 41 | allTasks.join(); // Block until all tasks complete 42 | 43 | System.out.println("Order processing completed successfully"); 44 | finalizeOrder(order); 45 | } 46 | } 47 | ``` 48 | 49 | **Advantages:** 50 | - True parallelism with maximum performance 51 | - Clean, readable code structure 52 | - Built-in coordination mechanism 53 | - Easy to extend with additional tasks 54 | 55 | **Disadvantages:** 56 | - Basic error handling requires additional work 57 | - No built-in result aggregation for return values 58 | 59 | ### Approach 2: Sequential Task Chaining 60 | 61 | When tasks have dependencies, use `thenRunAsync()` for sequential execution. 62 | 63 | ```java 64 | public void processOrderSequentially(Order order) { 65 | CompletableFuture pipeline = CompletableFuture 66 | .runAsync(() -> validateOrder(order)) 67 | .thenRunAsync(() -> processPayment(order)) 68 | .thenRunAsync(() -> updateInventory(order)) 69 | .thenRunAsync(() -> sendConfirmationEmail(order)); 70 | 71 | pipeline.join(); 72 | } 73 | ``` 74 | 75 | **Use Case:** When payment must succeed before inventory updates, or when email should only send after payment confirmation. 76 | 77 | **Trade-off:** Sequential execution sacrifices parallelism for dependency management. 78 | 79 | ### Approach 3: Result Collection and Aggregation 80 | 81 | When tasks return meaningful results that need to be collected: 82 | 83 | ```java 84 | public OrderResult processOrderWithResults(Order order) { 85 | CompletableFuture validation = CompletableFuture 86 | .supplyAsync(() -> validateOrder(order)); 87 | 88 | CompletableFuture payment = CompletableFuture 89 | .supplyAsync(() -> processPayment(order)); 90 | 91 | CompletableFuture inventory = CompletableFuture 92 | .supplyAsync(() -> updateInventory(order)); 93 | 94 | CompletableFuture notification = CompletableFuture 95 | .supplyAsync(() -> sendConfirmationEmail(order)); 96 | 97 | CompletableFuture allResults = CompletableFuture 98 | .allOf(validation, payment, inventory, notification) 99 | .thenApply(v -> new OrderResult( 100 | validation.join(), 101 | payment.join(), 102 | inventory.join(), 103 | notification.join() 104 | )); 105 | 106 | return allResults.join(); 107 | } 108 | ``` 109 | 110 | ## Enhanced Error Handling 111 | 112 | ### Individual Task Error Management 113 | 114 | ```java 115 | public void processOrderWithErrorHandling(Order order) { 116 | CompletableFuture validation = CompletableFuture 117 | .runAsync(() -> validateOrder(order), executor) 118 | .exceptionally(ex -> { 119 | logError("Order validation failed", ex); 120 | handleValidationFailure(order, ex); 121 | return null; 122 | }); 123 | 124 | CompletableFuture payment = CompletableFuture 125 | .runAsync(() -> processPayment(order), executor) 126 | .exceptionally(ex -> { 127 | logError("Payment processing failed", ex); 128 | initiateRefundProcess(order, ex); 129 | return null; 130 | }); 131 | 132 | // You can add more tasks with similar patterns if needed 133 | 134 | CompletableFuture allTasks = CompletableFuture 135 | .allOf(validation, payment) 136 | .whenComplete((result, ex) -> { 137 | if (ex != null) { 138 | logError("Overall order processing failed", ex); 139 | handleOverallFailure(order, ex); 140 | } else { 141 | finalizeSuccessfulOrder(order); 142 | } 143 | }); 144 | 145 | allTasks.join(); // Wait for completion 146 | } 147 | ``` 148 | you **can and should throw exceptions directly** in your task methods (like `validateOrder()`, `processPayment()`) when something goes wrong. This allows the `CompletableFuture`'s `.exceptionally()` or `.handle()` blocks to catch and process them cleanly. 149 | ```java 150 | public void validateOrder(Order order) { 151 | if (!isOrderValid(order)) { 152 | throw new InvalidRequestException("Order validation failed due to missing fields."); 153 | } 154 | // ... proceed with validation logic 155 | } 156 | ``` 157 | 158 | ## Timeout Management 159 | 160 | ### Individual Task Timeouts 161 | 162 | ```java 163 | public void processOrderWithTimeouts(Order order) { 164 | CompletableFuture validation = CompletableFuture 165 | .runAsync(() -> validateOrder(order), executor) 166 | .orTimeout(5, TimeUnit.SECONDS) 167 | .exceptionally(ex -> { 168 | if (ex instanceof TimeoutException) { 169 | logError("Validation timed out", ex); 170 | } 171 | return null; 172 | }); 173 | 174 | CompletableFuture payment = CompletableFuture 175 | .runAsync(() -> processPayment(order), executor) 176 | .orTimeout(30, TimeUnit.SECONDS) 177 | .exceptionally(ex -> { 178 | if (ex instanceof TimeoutException) { 179 | logError("Payment processing timed out", ex); 180 | initiatePaymentCancellation(order); 181 | } 182 | return null; 183 | }); 184 | 185 | // Configure other tasks similarly... 186 | } 187 | ``` 188 | 189 | ### Global Timeout Strategy 190 | 191 | ```java 192 | public void processOrderWithGlobalTimeout(Order order) { 193 | CompletableFuture allTasks = CompletableFuture.allOf( 194 | validation, payment, inventory, notification 195 | ); 196 | 197 | CompletableFuture result = allTasks 198 | .orTimeout(60, TimeUnit.SECONDS) 199 | .exceptionally(ex -> { 200 | if (ex instanceof TimeoutException) { 201 | logError("Overall order processing timed out", ex); 202 | cancelOrderProcessing(order); 203 | alertOperationsTeam(order); 204 | } 205 | return null; 206 | }); 207 | 208 | result.join(); 209 | } 210 | ``` 211 | 212 | ### Advanced Timeout with Watchdog 213 | 214 | ```java 215 | private final ScheduledExecutorService scheduler = 216 | Executors.newScheduledThreadPool(1); 217 | 218 | public void processOrderWithWatchdog(Order order) { 219 | CompletableFuture allTasks = CompletableFuture.allOf( 220 | validation, payment, inventory, notification 221 | ); 222 | 223 | ScheduledFuture watchdog = scheduler.schedule(() -> { 224 | if (!allTasks.isDone()) { 225 | logError("Order processing watchdog triggered"); 226 | escalateToManagement(order); 227 | } 228 | }, 90, TimeUnit.SECONDS); 229 | 230 | allTasks.whenComplete((result, ex) -> { 231 | watchdog.cancel(false); // Cancel watchdog on completion 232 | if (ex == null) { 233 | finalizeOrder(order); 234 | } 235 | }); 236 | 237 | allTasks.join(); 238 | } 239 | ``` 240 | 241 | ## Complete Production-Ready Example 242 | 243 | ```java 244 | @Service 245 | public class OrderProcessingService { 246 | private final ExecutorService executor; 247 | private final ScheduledExecutorService scheduler; 248 | 249 | public OrderProcessingService() { 250 | this.executor = Executors.newFixedThreadPool( 251 | Runtime.getRuntime().availableProcessors() 252 | ); 253 | this.scheduler = Executors.newScheduledThreadPool(2); 254 | } 255 | 256 | public CompletableFuture processOrderAsync(Order order) { 257 | return CompletableFuture.supplyAsync(() -> { 258 | try { 259 | // Create individual task futures 260 | CompletableFuture validation = createValidationTask(order); 261 | CompletableFuture payment = createPaymentTask(order); 262 | CompletableFuture inventory = createInventoryTask(order); 263 | CompletableFuture notification = createNotificationTask(order); 264 | 265 | // Wait for all tasks to complete 266 | CompletableFuture allTasks = CompletableFuture.allOf( 267 | validation, payment, inventory, notification 268 | ); 269 | 270 | // Set up global timeout 271 | allTasks.orTimeout(120, TimeUnit.SECONDS).join(); 272 | 273 | // Collect results 274 | return new OrderProcessingResult( 275 | validation.join(), 276 | payment.join(), 277 | inventory.join(), 278 | notification.join() 279 | ); 280 | 281 | } catch (Exception ex) { 282 | throw new OrderProcessingException("Order processing failed", ex); 283 | } 284 | }, executor); 285 | } 286 | 287 | private CompletableFuture createValidationTask(Order order) { 288 | return CompletableFuture 289 | .supplyAsync(() -> validateOrder(order), executor) 290 | .orTimeout(10, TimeUnit.SECONDS) 291 | .exceptionally(ex -> handleValidationError(order, ex)); 292 | } 293 | 294 | private CompletableFuture createPaymentTask(Order order) { 295 | return CompletableFuture 296 | .supplyAsync(() -> processPayment(order), executor) 297 | .orTimeout(45, TimeUnit.SECONDS) 298 | .exceptionally(ex -> handlePaymentError(order, ex)); 299 | } 300 | 301 | // Additional helper methods... 302 | 303 | @PreDestroy 304 | public void shutdown() { 305 | executor.shutdown(); 306 | scheduler.shutdown(); 307 | try { 308 | if (!executor.awaitTermination(30, TimeUnit.SECONDS)) { 309 | executor.shutdownNow(); 310 | } 311 | if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) { 312 | scheduler.shutdownNow(); 313 | } 314 | } catch (InterruptedException ex) { 315 | executor.shutdownNow(); 316 | scheduler.shutdownNow(); 317 | Thread.currentThread().interrupt(); 318 | } 319 | } 320 | } 321 | ``` 322 | 323 | ## Comparison Summary 324 | 325 | | Approach | Parallelism | Error Handling | Result Collection | Complexity | Best For | 326 | |----------|-------------|----------------|-------------------|------------|----------| 327 | | `allOf()` with `runAsync()` | ✅ Full | ⚠️ Manual | ❌ No | Low | Fire-and-forget tasks | 328 | | `allOf()` with `supplyAsync()` | ✅ Full | ⚠️ Manual | ✅ Yes | Medium | Tasks returning results | 329 | | Sequential chaining | ❌ None | ✅ Built-in | ✅ Yes | Low | Dependent tasks | 330 | | Enhanced with timeouts | ✅ Full | ✅ Comprehensive | ✅ Yes | High | Production systems | 331 | 332 | ## Best Practices 333 | 334 | 1. **Use appropriate thread pools**: Size pools based on task characteristics (CPU-bound vs I/O-bound) 335 | 2. **Implement proper timeout strategies**: Set reasonable timeouts for individual tasks and overall processing 336 | 3. **Handle exceptions gracefully**: Use `exceptionally()`, `handle()`, or `whenComplete()` for error management 337 | 4. **Clean up resources**: Always shut down executors properly to prevent resource leaks 338 | 5. **Monitor and log**: Include comprehensive logging for debugging and monitoring 339 | 6. **Consider circuit breakers**: For external service calls, implement circuit breaker patterns 340 | 7. **Test timeout scenarios**: Verify behavior under various failure and timeout conditions 341 | 342 | ## Recommended Solution 343 | 344 | For most e-commerce order processing scenarios, **Approach 1 with enhanced error handling and timeouts** provides the best balance of performance, maintainability, and robustness. It enables true parallelism while providing the flexibility to handle complex error scenarios and timeout requirements that are essential in production environments. -------------------------------------------------------------------------------- /file I O/wkg-with-file-IO.md: -------------------------------------------------------------------------------- 1 | ### readfile ex 2 | ```java 3 | // byte strams. 4 | import java.io.*; 5 | 6 | public class Demo { 7 | public static void main(String[] args) throws IOException { 8 | /*File f = new File("test.txt") 9 | 10 | System.out.println(f.exists());//false //true 11 | System.out.println(f.createNewFile());//true //false 12 | System.out.println(f.exists());//true //true 13 | 14 | FileOutputStream fos = new FileOutputStream(f); 15 | FileOutputStream fos = new FileOutputStream("test1.txt"); 16 | FileOutputStream fos = new FileOutputStream("test1.txt", true) ;*/ 17 | 18 | FileOutputStream fos = new FileOutputStream("test1.txt", false); 19 | fos.write(new byte[]{100, 97, 100}); 20 | fos.write(32); 21 | fos.write(new byte[]{65, 66, 67, 68, 69, 70}, 2, 4); 22 | fos.write(32); 23 | 24 | } 25 | } 26 | 27 | // char strams 28 | package com.kit; 29 | 30 | import java.io.FileInputStream; 31 | import java.io.IOException; 32 | 33 | public class Demo { 34 | public static void main(String[] args) throws IOException { 35 | FileInputStream fis = new FileInputStream("test.txt"); 36 | // File f1 = new File("C:\\Users\\admin\\Desktop\\Demo.java"); // Corrected path 37 | // ("C:/Users/admin/Desktop/Demo.java") // Alternatively you can 38 | int i = 0; 39 | while ((i = fis.read()) != -1) { 40 | System.out.print((char) i); 41 | } 42 | fis.close(); // Close the FileInputStream when done 43 | } 44 | } 45 | ``` 46 | ### wkg with File Decripter 47 | ```java 48 | import java.io.File; 49 | import java.io.FileDescriptor; 50 | import java.io.FileOutputStream; 51 | import java.io.IOException; 52 | 53 | public class Demo { 54 | public static void main(String[] args) throws IOException { 55 | File f = new File("check.txt"); 56 | FileOutputStream fos = new FileOutputStream(f); 57 | FileDescriptor fd = fos.getFD(); 58 | FileOutputStream fos1 = new FileOutputStream(fd); 59 | fos1.write("hello naresh it".getBytes()); 60 | } 61 | } 62 | ``` 63 | ### OOS & OIS 64 | ```java 65 | 66 | // OOS & OIS 67 | import java.io.*; 68 | 69 | class Student implements Serializable { 70 | String name = "Anil"; 71 | int sage = 29; 72 | double sfee = 2500; 73 | String scourse = "java"; 74 | String insName = "NIT"; 75 | 76 | static class SAndD { 77 | public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { 78 | FileOutputStream fos = new FileOutputStream("des"); 79 | ObjectOutputStream oos = new ObjectOutputStream(fos); 80 | Student s = new Student(); 81 | oos.writeObject(s); 82 | oos.close(); 83 | 84 | FileInputStream fis = new FileInputStream("des"); 85 | ObjectInputStream ois = new ObjectInputStream(fis); 86 | Object o = ois.readObject(); 87 | Student s1 = (Student) o; 88 | System.out.println(s1.sage); 89 | ois.close(); 90 | } 91 | } 92 | } 93 | ``` 94 | 95 | 96 | ### data streams 97 | ```java 98 | 99 | // Data streams 100 | 101 | import java.io.*; 102 | 103 | public class Demo { 104 | public static void main(String[] args) throws IOException { 105 | File file = new File("test2.txt"); 106 | FileOutputStream fos = new FileOutputStream(file); 107 | DataOutputStream dos = new DataOutputStream(fos); 108 | dos.write(100); 109 | dos.writeInt(200); 110 | dos.writeDouble(12.23d); 111 | dos.writeChar('a'); 112 | dos.writeUTF("ramchandra"); 113 | dos.writeBoolean(true); 114 | 115 | FileInputStream fis = new FileInputStream(file); 116 | DataInputStream dis = new DataInputStream(fis); 117 | 118 | System.out.println(dis.read()); 119 | System.out.println(dis.readInt()); 120 | System.out.println(dis.readDouble()); 121 | System.out.println(dis.readChar()); 122 | System.out.println(dis.readUTF()); 123 | System.out.println(dis.readBoolean()); 124 | 125 | dis.close(); // Close the streams when done 126 | dos.close(); 127 | } 128 | } 129 | 130 | ``` 131 | 132 | 133 | ### Restricting few feilds not to participate in Serialization Using Transient keyword. 134 | 135 | ``` java 136 | 137 | import java.io.*; 138 | 139 | public class Employee implements Serializable { 140 | int eid = 101; 141 | String ename = "ramchandar"; 142 | int esal = 7000; 143 | int eage = 30; 144 | String epassword = "ram123java"; 145 | 146 | //not participated in serialization.. will be null. 147 | transient String epassword = "ram123java"; 148 | 149 | /* 150 | private void writeObject(ObjectOutputStream oos) throws Exception { 151 | System.out.println("private writeobject method"); 152 | oos.defaultWriteObject(); 153 | } 154 | 155 | private void readObject(ObjectInputStream ois) throws Exception { 156 | System.out.println("private readobject method"); 157 | ois.defaultReadObject(); 158 | } 159 | 160 | private void readObject(ObjectInputStream ois) throws Exception { 161 | System.out.println("private readobject method"); 162 | ois.defaultReadObject(); 163 | String s = (String) ois.readObject(); 164 | System.out.println("s: " + s); 165 | } 166 | 167 | */ 168 | 169 | private void writeObject(ObjectOutputStream oos) throws Exception { 170 | System.out.println("private writeObject method"); 171 | oos.defaultWriteObject(); 172 | oos.writeObject("sbiicicinitram123kitjava.netpassword"); 173 | } 174 | 175 | private void readObject(ObjectInputStream ois) throws Exception { 176 | System.out.println("private readobject method"); 177 | ois.defaultReadObject(); 178 | String s = (String) ois.readObject(); 179 | String s1 = s.substring(11, 17); // 11 16 180 | String s2 = s.substring(20, 24); // 20 23 181 | epassword = s1 + "$2"; 182 | } 183 | } 184 | 185 | ``` 186 | 187 | ### externalization. 188 | ```java 189 | 190 | 191 | //externalization. 192 | 193 | import java.io.*; 194 | 195 | class ExDemo { 196 | public static void main(String[] args) throws IOException { 197 | File f = new File("emp.ext"); 198 | FileOutputStream fos = new FileOutputStream(f); 199 | ObjectOutputStream oos = new ObjectOutputStream(fos); 200 | Employee e = new Employee(101, "ram", 7000.00, "dev", "amt"); 201 | oos.writeObject(e); 202 | System.out.println(" completed"); 203 | } 204 | 205 | /* 206 | @Override 207 | public void writeExternal(ObjectOutput oo) throws IOException { 208 | System.out.println("writeExternal method executing"); 209 | } 210 | 211 | @Override 212 | public void readExternal(ObjectInput oi) throws IOException { 213 | System.out.println("readExternal method executing"); 214 | } 215 | 216 | */ 217 | 218 | @Override 219 | public void writeExternal(ObjectOutput oo) throws IOException { 220 | System.out.println("writeExternal method executing"); 221 | oo.writeObject(ename); 222 | oo.writeObject(edeptname); 223 | } 224 | 225 | @Override 226 | public void readExternal(ObjectInput oi) throws IOException { 227 | System.out.println("readExternal method executing"); 228 | ename = (String) oi.readObject(); 229 | } 230 | 231 | } 232 | 233 | 234 | ``` 235 | 236 | ### wkg with serializable and inheritance. 237 | 238 | ```java 239 | 240 | // wkg with serializable and inheritance. 241 | 242 | 243 | import java.io.*; 244 | class C implements Serializable { 245 | String s = "NIT"; 246 | } 247 | 248 | class B implements Serializable { 249 | C obj3 = new C(); 250 | } 251 | 252 | class A implements Serializable { 253 | B obj2 = new B(); 254 | } 255 | 256 | public class SHDemo { 257 | public static void main(String[] args) throws IOException { 258 | File f = new File("test.txt"); 259 | FileOutputStream fos = new FileOutputStream(f); 260 | ObjectOutputStream oos = new ObjectOutputStream(fos); 261 | A obj = new A(); 262 | oos.writeObject(obj); 263 | System.out.println("serialization completed"); 264 | 265 | File f1 = new File("test.txt"); 266 | FileInputStream fis = new FileInputStream(f1); 267 | ObjectInputStream ois = new ObjectInputStream(fis); 268 | Object o = ois.readObject(); 269 | } 270 | } 271 | 272 | ``` 273 | 274 | 275 | ### ByteArrayOutputStream 276 | ```java 277 | 278 | /** java.io.ByteArrayOutputStream 279 | * 280 | * It is useful for sending the same data from java application to multiple times at a time. 281 | */ 282 | import java.io.*; 283 | 284 | public class BAOSDemo { 285 | public static void main(String[] args) throws IOException { 286 | FileOutputStream fos1 = new FileOutputStream("test1.txt"); 287 | FileOutputStream fos2 = new FileOutputStream("test2.txt"); 288 | FileOutputStream fos3 = new FileOutputStream("test3.txt"); 289 | 290 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 291 | bos.write(new byte[]{100, 97, 100, 32}); // d 292 | bos.write(new byte[]{109, 111, 109}); 293 | 294 | bos.writeTo(fos1); 295 | bos.writeTo(fos2); 296 | bos.writeTo(fos3); 297 | 298 | System.out.println("process completed"); 299 | } 300 | } 301 | 302 | ``` 303 | 304 | ### SequenceInputStream 305 | ```java 306 | 307 | // wkg with SequenceInputStream 308 | 309 | import java.io.*; 310 | 311 | public class Student implements java.io.Serializable { 312 | private static final long serialVersionUID = 900L; 313 | int sid = 101; 314 | String sname = "varun"; 315 | int sage = 25; 316 | String scourse = "java"; 317 | } 318 | 319 | public class SISDemo { 320 | public static void main(String[] s) throws IOException { 321 | File f1 = new File("t1.txt"); 322 | File f2 = new File("t2.txt"); 323 | 324 | FileInputStream fis1 = new FileInputStream(f1); 325 | FileInputStream fis2 = new FileInputStream(f2); 326 | 327 | SequenceInputStream sis = new SequenceInputStream(fis2, fis1); 328 | int i = 0; 329 | while ((i = sis.read()) != -1) { 330 | System.out.print((char) i); 331 | } 332 | } 333 | } 334 | ``` 335 | 336 | ### wkg with File Writer 337 | ```java 338 | 339 | //wkg with File Writer 340 | import java.io.File; 341 | import java.io.FileWriter; 342 | import java.io.IOException; 343 | 344 | public class FWDemo { 345 | public static void main(String[] args) throws IOException { 346 | File f = new File("test.txt"); 347 | FileWriter fw = new FileWriter(f); 348 | char[] c = {'n', 'i', 't'}; 349 | fw.write(c); 350 | fw.write(32); 351 | fw.write("karthikit"); 352 | fw.write(32); 353 | char[] c1 = {'a', 'b', 'c', 'd', 'e', 'f'}; 354 | fw.write(c1, 2, 3); 355 | fw.write(32); 356 | fw.write("internationalization", 5, 6); 357 | fw.flush(); 358 | fw.close(); 359 | } 360 | } 361 | ``` 362 | ### wkg with File Reader 363 | ```java 364 | 365 | //wkg with File Reader 366 | 367 | c class FRDemo { 368 | ublic static void main(String[] args) throws IOException{ 369 | File f = new File("test.txt"); 370 | FileReader fr = new FileReader(f); 371 | int i =0; 372 | while((i=fr.read()) !=- 1){ 373 | System.out.print((char)i); 374 | 375 | System.out.println("\nprogram ends"); 376 | 377 | 378 | import java.io.File; 379 | import java.io.FileReader; 380 | import java.io.FileNotFoundException; 381 | import java.io.IOException; 382 | 383 | public class Test { 384 | public static void main(String[] args) { //throws F 385 | File f = new File("test.txt"); 386 | try (FileReader fr = new FileReader(f)) { 387 | int i = 0; 388 | while ((i = fr.read()) != -1) { 389 | System.out.print((char) i); 390 | } 391 | } catch (FileNotFoundException e) { 392 | e.printStackTrace(); 393 | } catch (IOException e) { 394 | e.printStackTrace(); 395 | } 396 | } 397 | } 398 | ``` 399 | 400 | 401 | 402 | ```java 403 | 404 | /* 405 | what is object? 406 | real time world existing thing. has haracterstics 407 | -> Behaviour : differentiate one object to another 408 | -> Properties : hold the data accNo, accHolderName, pin 409 | -> functionalities : doing some operation on propertis 410 | withdrawl() 411 | deposit() 412 | balance enquiry() 413 | */ 414 | 415 | 416 | 417 | 418 | 419 | class SuperClass { 420 | // Static variable 421 | static int staticVar = 10; 422 | // Instance variable 423 | int instanceVar = 20; 424 | 425 | // Static method 426 | static void staticMethod() { 427 | System.out.println("Static method in SuperClass"); 428 | } 429 | 430 | // Instance method 431 | void instanceMethod() { 432 | System.out.println("Instance method in SuperClass"); 433 | } 434 | } 435 | class SubClass extends SuperClass { 436 | 437 | // Static variable (hidden, not overridden) 438 | static int staticVar = 30; 439 | // Instance variable (hidden, not overridden) 440 | int instanceVar = 40; 441 | 442 | // Static method (hidden, not overridden) 443 | static void staticMethod() { 444 | System.out.println("Static method in SubClass"); 445 | } 446 | 447 | // Instance method (overridden) 448 | @Override 449 | void instanceMethod() { 450 | System.out.println("Instance method in SubClass"); 451 | } 452 | } 453 | 454 | 455 | public class Main { 456 | public static void main(String[] args) { 457 | // Upcasting 458 | SuperClass superClassRef = new SubClass(); 459 | 460 | // Accessing static variable 461 | System.out.println("Static Variable: " + superClassRef.staticVar); // Output: 10 (SuperClass static variable) 462 | 463 | // Accessing instance variable 464 | System.out.println("Instance Variable: " + superClassRef.instanceVar); // Output: 20 (SuperClass instance variable) 465 | 466 | // Calling static method 467 | superClassRef.staticMethod(); // Output: Static method in SuperClass (SuperClass static method) 468 | 469 | // Calling instance method 470 | superClassRef.instanceMethod(); // Output: Instance method in SubClass (SubClass instance method) 471 | 472 | System.out.println("-------------------------------------------------------------------------------"); 473 | 474 | 475 | 476 | 477 | 478 | SubClass subClassRef=(SubClass)superClassRef ; 479 | 480 | // Accessing static variable 481 | System.out.println("Static Variable: " + subClassRef.staticVar); // Output: 10 (SuperClass static variable) 482 | 483 | // Accessing instance variable 484 | System.out.println("Instance Variable: " + subClassRef.instanceVar); // Output: 20 (SuperClass instance variable) 485 | 486 | // Calling static method 487 | subClassRef.staticMethod(); // Output: Static method in SuperClass (SuperClass static method) 488 | 489 | // Calling instance method 490 | subClassRef.instanceMethod(); // Output: Instance method in SubClass (SubClass instance method) 491 | 492 | // Obj is created using the Subclass, later it get upcasted. 493 | // Access using subclass reference 494 | System.out.println("Static Variable (SubClass): " + subClassRef.staticVar); // Output: 30 495 | System.out.println("Instance Variable (SubClass): " + subClassRef.instanceVar); // Output: 40 496 | subClassRef.staticMethod(); // Output: Static method in SubClass 497 | subClassRef.instanceMethod(); // Output: Instance method in SubClass 498 | 499 | // Upcasting to superclass reference 500 | SuperClass superClassRef = subClassRef; 501 | 502 | // Access using superclass reference 503 | System.out.println("Static Variable (SuperClass): " + superClassRef.staticVar); // Output: 10 504 | System.out.println("Instance Variable (SuperClass): " + superClassRef.instanceVar); // Output: 20 505 | superClassRef.staticMethod(); // Output: Static method in SuperClass 506 | superClassRef.instanceMethod(); // Output: Instance method in SubClass 507 | } 508 | } 509 | 510 | 511 | ``` -------------------------------------------------------------------------------- /java-8/functional-interface.md: -------------------------------------------------------------------------------- 1 | I'll refactor and restructure the provided documentation about Functional Interfaces and Java 8 features into a comprehensive markdown format. 2 | 3 | # Java 8 Functional Programming Guide 4 | 5 | A comprehensive overview of functional programming concepts in Java 8, including functional interfaces, lambda expressions, method references, and built-in functional interfaces. This guide provides practical examples and clear explanations of core concepts. 6 | 7 | --- 8 | 9 | ## Table of Contents 10 | 11 | | # | Topic | 12 | |----|-------------------------------------------------------------| 13 | | **Fundamentals of Functional Interfaces** | | 14 | | 1 | [What is a Functional Interface?](#what-is-a-functional-interface) | 15 | | 2 | [Default Methods in Interfaces](#default-methods-in-interfaces) | 16 | | 3 | [Static Methods in Interfaces](#static-methods-in-interfaces) | 17 | | 4 | [Private Methods in Interfaces](#private-methods-in-interfaces) | 18 | | 5 | [Interface vs Abstract Class](#interface-vs-abstract-class) | 19 | 20 | 21 | 22 | ## What is a Functional Interface? 23 | 24 | A functional interface is a special type of interface introduced in Java 8 that contains exactly one abstract method. 25 | 26 | ### Key Characteristics: 27 | 28 | * Annotated with `@FunctionalInterface` (optional but recommended) 29 | * Contains only one abstract method 30 | * Can have any number of default and static methods.(since java 9+ you can have private methods.) 31 | * Can include methods from the `java.lang.Object` class 32 | * Supports functional programming paradigms in Java 33 | 34 | ### Implementation Methods: 35 | 36 | There are four ways to provide implementation for functional interfaces: 37 | 38 | 1. By writing a separate implementation class 39 | 2. By writing an anonymous inner class 40 | 3. By writing lambda expressions 41 | 4. By writing method references 42 | 43 | ### Example: Basic Functional Interface 44 | 45 | ```java 46 | @FunctionalInterface 47 | interface I { 48 | void m1(); // Single abstract method 49 | 50 | // Object class methods don't count against the single abstract method rule 51 | String toString(); 52 | int hashCode(); 53 | 54 | private void ex() { } 55 | } 56 | 57 | // Implementation using a separate class 58 | class Impl implements I { 59 | public void m1() { 60 | System.out.println("m1 method-Impl"); 61 | } 62 | } 63 | 64 | public class Test { 65 | public static void main(String[] args) { 66 | I obj = new Impl(); 67 | obj.m1(); // Output: m1 method-Impl 68 | } 69 | } 70 | ``` 71 | 72 | > Note: `toString()` and `hashCode()` methods are being implemented by `java.lang.Object` class, so they don't violate the single abstract method rule. 73 | 74 | 75 | 76 | > `toString()` and `hashCode()` are methods from `Object`, so **they do not count** toward the abstract method count of a functional interface. The compiler ignores them when validating `@FunctionalInterface`. 77 | 78 | ### Example: Functional Interface with Inheritance 79 | 80 | ```java 81 | @FunctionalInterface 82 | interface I { 83 | void m1(); 84 | } 85 | 86 | @FunctionalInterface 87 | interface J extends I { 88 | // No new abstract method - J inherits m1() from I 89 | } 90 | 91 | public class Test { 92 | public static void main(String[] args) { 93 | // Creating an instance of interface J using anonymous inner class 94 | J obj = new J() { 95 | @Override 96 | public void m1() { 97 | System.out.println("m1-anonymous"); 98 | } 99 | }; 100 | 101 | obj.m1(); // Output: m1-anonymous 102 | } 103 | } 104 | ``` 105 | 106 | [Back to Top](#table-of-contents) 107 | 108 | ## Default Methods in Interfaces 109 | 110 | Default methods were introduced in Java 8 to enable interface evolution without breaking existing implementations. They provide a default implementation that can be overridden by implementing classes. 111 | 112 | ### Key Characteristics: 113 | 114 | * Defined with the `default` keyword 115 | * Implicitly `public` (no need to specify the modifier) 116 | * Provide implementation directly within the interface 117 | * Can be overridden by implementing classes 118 | * Help solve the "multiple inheritance of behavior" problem 119 | 120 | ### Example: Basic Default Method 121 | 122 | ```java 123 | interface Printable { 124 | // Abstract method 125 | void print(String message); 126 | 127 | // Default method 128 | default void printDefault() { 129 | System.out.println("Default implementation"); 130 | } 131 | } 132 | 133 | class PrintImpl implements Printable { 134 | @Override 135 | public void print(String message) { 136 | System.out.println("Message: " + message); 137 | } 138 | 139 | // Optional: Override the default method 140 | @Override 141 | public void printDefault() { 142 | System.out.println("Overridden default implementation"); 143 | } 144 | } 145 | ``` 146 | 147 | ### Example: Multiple Inheritance with Default Methods 148 | 149 | ```java 150 | interface Square { 151 | default void cal(int x) { 152 | System.out.println("The Square Of A Given Number: " + x * x); 153 | } 154 | } 155 | 156 | interface Cube { 157 | default void cal(int x) { 158 | System.out.println("The Cube Of A Given Number: " + x * x * x); 159 | } 160 | } 161 | 162 | class A implements Square, Cube { 163 | // Must override to resolve method conflict 164 | @Override 165 | public void cal(int x) { 166 | System.out.println("This is implementation"); 167 | Square.super.cal(50); // Calling Square's default method 168 | } 169 | } 170 | 171 | public class Main { 172 | public static void main(String[] args) { 173 | Cube obj = new A(); 174 | obj.cal(100); 175 | 176 | /* Output: 177 | This is implementation 178 | The Square Of A Given Number: 2500 179 | */ 180 | } 181 | } 182 | ``` 183 | 184 | [Back to Top](#table-of-contents) 185 | 186 | ## Static Methods in Interfaces 187 | 188 | Static methods in interfaces were introduced in Java 8 to provide utility methods that are relevant to the interface but don't require an instance. 189 | 190 | ### Key Characteristics: 191 | 192 | * Defined with the `static` keyword 193 | * Implicitly `public` (though you can explicitly declare them as such) 194 | * Cannot be overridden by implementing classes 195 | * Accessed using the interface name, not through an instance 196 | 197 | ### Example: Static Methods in Interface 198 | 199 | ```java 200 | interface I { 201 | static void m3() { 202 | System.out.println("This is static m3 method of I interface"); 203 | } 204 | } 205 | 206 | class A implements I { 207 | // This is NOT overriding the interface's static method 208 | // It's a completely separate method 209 | static void m3() { 210 | System.out.println("This is static m3 method of class A"); 211 | } 212 | } 213 | 214 | public class Test { 215 | public static void main(String[] args) { 216 | I.m3(); // Output: This is static m3 method of I interface 217 | A.m3(); // Output: This is static m3 method of class A 218 | } 219 | } 220 | ``` 221 | 222 | > Note: Static methods in interfaces cannot be overridden in the implementing class. If you define a method with the same signature, it will be treated as a new method in the class. 223 | 224 | 225 | ## Private Methods in Interfaces 226 | 227 | Private methods in interfaces were introduced in Java 9 to improve code reusability within interfaces. 228 | 229 | ### Key Characteristics: 230 | 231 | * Can be either `private` or `private static` 232 | * Help avoid code duplication in default and static methods 233 | * Cannot be accessed outside the interface 234 | * Enhance encapsulation within interfaces 235 | 236 | ### Example: Private Methods in Interface 237 | 238 | ```java 239 | public interface CustomInterface { 240 | void abstractMethod(); // Abstract method 241 | 242 | default void defaultMethod() { 243 | // Calling private helper method to increase reusability 244 | privateMethod(); 245 | System.out.println("Default method"); 246 | } 247 | 248 | static void staticMethod() { 249 | // Calling private static helper method 250 | privateStaticMethod(); 251 | System.out.println("Static method"); 252 | } 253 | 254 | // Private helper method for default methods 255 | private void privateMethod() { 256 | System.out.println("Private method"); 257 | } 258 | 259 | // Private static helper method for static methods 260 | private static void privateStaticMethod() { 261 | System.out.println("Private static method"); 262 | } 263 | } 264 | 265 | public class Main implements CustomInterface { 266 | public static void main(String[] args) { 267 | CustomInterface customInterface = new Main(); 268 | customInterface.defaultMethod(); 269 | /* 270 | Output: 271 | Private method 272 | Default method 273 | */ 274 | 275 | customInterface.abstractMethod(); // Output: Abstract method 276 | 277 | CustomInterface.staticMethod(); 278 | /* 279 | Output: 280 | Private static method 281 | Static method 282 | */ 283 | } 284 | 285 | @Override 286 | public void abstractMethod() { 287 | System.out.println("Abstract method"); 288 | } 289 | } 290 | ``` 291 | 292 | [Back to Top](#table-of-contents) 293 | 294 | ## Interface vs Abstract Class 295 | 296 | Understanding the differences between interfaces and abstract classes is crucial for proper design decisions in Java. 297 | 298 | ### Comparison Table: 299 | 300 | | Feature | Interface | Abstract Class | 301 | |---------|-----------|----------------| 302 | | Variables | Always `public static final` | Can be `private`, `public`, `static`, `protected`, `final` | 303 | | Variable initialization | Only declaration, no initialization | Can initialize variables | 304 | | Blocks/Initializers | Cannot write blocks (instance/static) | Can include both static and instance initializers | 305 | | Constructors | Cannot write constructors | Can write constructors | 306 | | Object creation | Cannot create objects, only reference variables | Cannot instantiate directly, but can be extended | 307 | | State representation | Doesn't represent object state | May represent object state | 308 | | Methods | Abstract, default, static, private (Java 9+) | Abstract and concrete methods | 309 | | Default methods | Supported | Not applicable (uses regular methods) | 310 | | Multiple inheritance | Supported | Not supported | 311 | | Object class methods | Cannot directly override | Can override | 312 | 313 | 314 | 315 | [Back to Top](#table-of-contents) 316 | 317 | -------------------------------------------------------------------------------- /java-8/lambda-expressions.md: -------------------------------------------------------------------------------- 1 | 2 | ## Table of Contents 3 | | # | Topic | 4 | |----|-------------------------------------------------------------| 5 | | **Lambda Expressions** | | 6 | | 1 | [Understanding Lambda Expressions](#understanding-lambda-expressions) | 7 | | 2 | [Blocked vs Unblocked Lambda](#blocked-vs-unblocked-lambda) | 8 | | 3 | [Pure Functions](#pure-functions) | 9 | | 4 | [Higher Order Functions](#higher-order-functions) | 10 | 11 | 12 | 13 | ## Understanding Lambda Expressions 14 | 15 | Lambda expressions provide a concise way to represent anonymous functions that can be passed as arguments or stored in variables. 16 | 17 | ### Key Characteristics: 18 | 19 | * Anonymous functions (unnamed functions/expressions) 20 | * Provide implementation for functional interfaces 21 | * Enable more concise and readable code 22 | * Suitable for collection framework operations 23 | * Support functional programming paradigms 24 | 25 | ### Basic Syntax: 26 | 27 | ``` 28 | (parameters) -> { statements } 29 | ``` 30 | 31 | ### Example: Simple Lambda Expressions 32 | 33 | ```java 34 | @FunctionalInterface 35 | interface I { 36 | void m1(); 37 | } 38 | 39 | interface J { 40 | void m2(int x); 41 | } 42 | 43 | public class Test { 44 | public static void main(String[] args) { 45 | // Simple lambda with no parameters 46 | I obj = () -> System.out.println("m1-lambda"); 47 | obj.m1(); // Output: m1-lambda 48 | 49 | // Lambda with one parameter (with type) 50 | J obj2 = (int k) -> System.out.println("k: " + k); 51 | obj2.m2(123); // Output: k: 123 52 | 53 | // Lambda with one parameter (type inference) 54 | J obj4 = x -> System.out.println("x: " + x); 55 | obj4.m2(123); // Output: x: 123 56 | } 57 | } 58 | ``` 59 | 60 | ### Example: Lambda with Return Value 61 | 62 | ```java 63 | @FunctionalInterface 64 | interface Square { 65 | int area(int x); 66 | } 67 | 68 | public class Main { 69 | static void m1(Square obj) { 70 | System.out.println(obj.hashCode()); 71 | System.out.println(obj.area(25)); // Output: 625 72 | } 73 | 74 | public static void main(String[] args) { 75 | // Lambda with return value 76 | Square s = (int value) -> { 77 | return value * value; 78 | }; 79 | 80 | System.out.println(s.hashCode()); 81 | System.out.println(s.area(10)); // Output: 100 82 | 83 | m1(s); 84 | 85 | // Passing lambda directly as an argument 86 | System.out.println(m1((int value) -> { 87 | return value * value; 88 | })); 89 | } 90 | } 91 | ``` 92 | 93 | > Note: The `hashCode()` method is implemented by the anonymous class created from the lambda expression. 94 | 95 | [Back to Top](#table-of-contents) 96 | 97 | ## Blocked vs Unblocked Lambda 98 | 99 | Lambda expressions can be categorized as blocked or unblocked based on their syntax and format. 100 | 101 | ### Unblocked Lambda: 102 | 103 | * Single expression without curly braces 104 | * Implicit return for functions returning a value 105 | * More concise syntax 106 | 107 | ### Blocked Lambda: 108 | 109 | * Multiple statements enclosed in curly braces `{}` 110 | * Explicit `return` statement for functions returning a value 111 | * Can include variable declarations, multiple operations, etc. 112 | 113 | ### Example: Comparison of Both Styles 114 | 115 | ```java 116 | @FunctionalInterface 117 | interface Calculator { 118 | int calculate(int x, int y); 119 | } 120 | 121 | public class LambdaStyles { 122 | public static void main(String[] args) { 123 | // Unblocked lambda - single expression, implicit return 124 | Calculator add = (x, y) -> x + y; 125 | System.out.println("Addition: " + add.calculate(5, 3)); // Output: Addition: 8 126 | 127 | // Blocked lambda - multiple statements, explicit return 128 | Calculator multiply = (x, y) -> { 129 | int result = x * y; 130 | System.out.println("Computing product of " + x + " and " + y); 131 | return result; 132 | }; 133 | System.out.println("Multiplication: " + multiply.calculate(5, 3)); 134 | /* 135 | Output: 136 | Computing product of 5 and 3 137 | Multiplication: 15 138 | */ 139 | } 140 | } 141 | ``` 142 | 143 | [Back to Top](#table-of-contents) 144 | 145 | ## Pure Functions 146 | 147 | Pure functions are a fundamental concept in functional programming that follow specific principles to ensure predictable behavior. 148 | 149 | ### Key Characteristics: 150 | 151 | * No side effects: doesn't modify state outside its scope 152 | * Output depends solely on input parameters 153 | * For the same input, always returns the same output 154 | * Makes code more predictable and testable 155 | 156 | ### Example: Pure Function 157 | 158 | ```java 159 | @FunctionalInterface 160 | interface MathOperation { 161 | int perform(int x, int y); 162 | } 163 | 164 | public class PureFunctionDemo { 165 | public static void main(String[] args) { 166 | // Pure function: result depends only on inputs 167 | MathOperation multiply = (int x, int y) -> x * y; 168 | 169 | System.out.println(multiply.perform(10, 20)); // Output: 200 170 | System.out.println(multiply.perform(10, 20)); // Output: 200 (always the same for same inputs) 171 | } 172 | } 173 | ``` 174 | 175 | ### Example: Impure Function 176 | 177 | ```java 178 | @FunctionalInterface 179 | interface I { 180 | String transform(int x, int y); 181 | } 182 | 183 | public class Test { 184 | static int a = 10; 185 | 186 | public static void main(String[] args) { 187 | int b = 20; 188 | 189 | // Impure function: modifies external state 190 | I obj = (int x, int y) -> { 191 | a = 20; // Modifying static variable - side effect 192 | // b = 10; // Would cause error: local variables must be final or effectively final 193 | return Integer.toString(x * y); 194 | }; 195 | 196 | System.out.println(obj.transform(10, 20)); // Output: 200 197 | System.out.println("Modified a: " + a); // Output: Modified a: 20 198 | } 199 | } 200 | ``` 201 | 202 | [Back to Top](#table-of-contents) 203 | 204 | ## Higher Order Functions 205 | 206 | Higher-order functions are functions that can take other functions as parameters or return functions as results. 207 | 208 | ### Key Characteristics: 209 | 210 | * Take one or more functions as input parameters 211 | * May return a function as output 212 | * Enable composition and reuse of behavior 213 | * Core concept in functional programming 214 | 215 | ### Example: Higher Order Function 216 | 217 | ```java 218 | interface I { 219 | int m1(); 220 | } 221 | 222 | @FunctionalInterface 223 | interface J { 224 | int m2(); 225 | } 226 | 227 | @FunctionalInterface 228 | interface K { 229 | // Higher-order function: Takes two functional interfaces as parameters 230 | void m3(I obj1, J obj2); 231 | } 232 | 233 | class A { 234 | void m4() { 235 | System.out.println("m4()"); 236 | } 237 | } 238 | 239 | public class Test { 240 | public static void main(String[] args) { 241 | // First function 242 | I obj1 = () -> { 243 | return 111; 244 | }; 245 | 246 | // Second function 247 | J obj2 = () -> { 248 | return 222; 249 | }; 250 | 251 | // Higher-order function that accepts two functions 252 | K obj3 = (I x, J y) -> { 253 | System.out.println(x.m1() + y.m2()); // Using the input functions 254 | A obj4 = new A(); 255 | obj4.m4(); 256 | }; 257 | 258 | // Pass functions as arguments 259 | obj3.m3(obj1, obj2); 260 | 261 | /* 262 | Output: 263 | 333 264 | m4() 265 | */ 266 | } 267 | } 268 | ``` 269 | 270 | [Back to Top](#table-of-contents) -------------------------------------------------------------------------------- /java-8/method-references.md: -------------------------------------------------------------------------------- 1 | 2 | ## Table of Contents 3 | | # | Topic | 4 | |----|-------------------------------------------------------------| 5 | | **Method References** | | 6 | | 1 | [Method References Basics](#method-references-basics) | 7 | | 2 | [Types of Method References](#types-of-method-references) | 8 | 9 | 10 | 11 | ## Method References Basics 12 | 13 | Method references provide a way to refer to methods or constructors without invoking them, offering a more concise alternative to lambda expressions in certain scenarios. 14 | 15 | ### Key Characteristics: 16 | 17 | * Provide implementation for functional interfaces 18 | * Reference existing method implementations 19 | * Create more readable and concise code 20 | * Use the `::` operator for reference 21 | * Internally create lambda expressions 22 | 23 | ### Example: Basic Method Reference 24 | 25 | ```java 26 | @FunctionalInterface 27 | interface Printable { 28 | void print(String message); 29 | } 30 | 31 | public class Main { 32 | public static void main(String[] args) { 33 | // Method reference to a static method 34 | Printable printable = System.out::println; 35 | printable.print("Hello"); // Output: Hello 36 | 37 | // Equivalent lambda expression 38 | Printable printableLambda = (String msg) -> System.out.println(msg); 39 | printableLambda.print("Hello"); // Output: Hello 40 | } 41 | } 42 | ``` 43 | 44 | ### Example: Method Reference to Static Method 45 | 46 | ```java 47 | @FunctionalInterface 48 | interface I { 49 | void m1(); 50 | } 51 | 52 | class A { 53 | static public void test() { 54 | System.out.println("Implementation for m1-I"); 55 | } 56 | } 57 | 58 | public class Test { 59 | public static void main(String[] args) { 60 | // Method reference to static method 61 | I obj = A::test; 62 | 63 | /* Equivalent lambda expression created internally: 64 | () -> { System.out.println("Implementation for m1-I"); } 65 | */ 66 | 67 | obj.m1(); // Output: Implementation for m1-I 68 | } 69 | } 70 | ``` 71 | 72 | [Back to Top](#table-of-contents) 73 | 74 | ## Types of Method References 75 | 76 | Java 8 supports four types of method references, each with its specific use case and syntax. 77 | 78 | ### 1. Reference to a Static Method 79 | 80 | ```java 81 | ClassName::staticMethodName 82 | ``` 83 | 84 | ### 2. Reference to an Instance Method of a Particular Object 85 | 86 | ```java 87 | objectName::instanceMethodName 88 | ``` 89 | 90 | ### 3. Reference to an Instance Method of an Arbitrary Object of a Particular Type 91 | 92 | ```java 93 | ClassName::instanceMethodName 94 | ``` 95 | 96 | ### 4. Reference to a Constructor 97 | 98 | ```java 99 | ClassName::new 100 | ``` 101 | 102 | ### Example: Different Types of Method References 103 | 104 | ```java 105 | import java.util.function.BiFunction; 106 | import java.util.function.Function; 107 | import java.util.function.Supplier; 108 | 109 | class Person { 110 | private String name; 111 | 112 | public Person(String name) { 113 | this.name = name; 114 | } 115 | 116 | public String getName() { 117 | return name; 118 | } 119 | 120 | public static int compareByName(Person p1, Person p2) { 121 | return p1.getName().compareTo(p2.getName()); 122 | } 123 | } 124 | 125 | public class MethodReferenceDemo { 126 | public static void main(String[] args) { 127 | // 1. Reference to a static method 128 | BiFunction comparator = Person::compareByName; 129 | 130 | // 2. Reference to an instance method of a particular object 131 | Person person = new Person("John"); 132 | Supplier nameSupplier = person::getName; 133 | System.out.println(nameSupplier.get()); // Output: John 134 | 135 | // 3. Reference to an instance method of an arbitrary object 136 | Function nameFunction = Person::getName; 137 | System.out.println(nameFunction.apply(new Person("Alice"))); // Output: Alice 138 | 139 | // 4. Reference to a constructor 140 | Function personCreator = Person::new; 141 | Person newPerson = personCreator.apply("Bob"); 142 | System.out.println(newPerson.getName()); // Output: Bob 143 | } 144 | } 145 | ``` 146 | 147 | ### Example: Using Method Reference with Functional Interface 148 | 149 | ```java 150 | public interface FunctionalInterfaceDemo { 151 | void singleAbstMethod(); 152 | 153 | default void printName() { 154 | System.out.println("Welcome to Code Decode"); 155 | } 156 | 157 | default void printName2() { 158 | System.out.println("Welcome to Code Decode"); 159 | } 160 | } 161 | 162 | class Test { 163 | public static void testImplementation() { 164 | System.out.println("This is test implementation of your abstract method"); 165 | } 166 | } 167 | 168 | public class Main { 169 | public static void main(String[] args) { 170 | // Using method reference to implement the functional interface 171 | FunctionalInterfaceDemo functionalInterfaceDemo = Test::testImplementation; 172 | functionalInterfaceDemo.singleAbstMethod(); // Output: This is test implementation of your abstract method 173 | 174 | // Using lambda expression 175 | FunctionalInterfaceDemo f = () -> System.out.println("IMPLEMENTATION of SAM"); 176 | f.singleAbstMethod(); // Output: IMPLEMENTATION of SAM 177 | } 178 | } 179 | ``` 180 | 181 | 182 | [Back to Top](#table-of-contents) 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /java-8/optional-class.md: -------------------------------------------------------------------------------- 1 | # Java 8 Optional Class 2 | 3 | ## Introduction 4 | 5 | As Java programmers, we often encounter `NullPointerException`. Java 8 introduced the `Optional` class in the `java.util` package to help avoid null checks and these exceptions. `Optional` is a container object that may or may not contain a non-null value. It essentially wraps an object to indicate the possible absence of a value. 6 | 7 | --- 8 | ### Additional Resources 9 | 10 | If you found this guide helpful, you might also be interested in my other Spring Framework resources: 11 | - [Core Java & Java-8 Interview Questions](https://github.com/anilvn/Java-Interview-Questions/tree/main) 12 | - [Spring Boot Interview Questions](https://github.com/anilvn/spring-boot-interview-questions/tree/main) 13 | - [Microservices with Spring Cloud Tutorials](https://javatechonline.com/microservices-tutorial/) 14 | 15 | Feel free to star and fork these repositories if you find them useful! 16 | 17 | --- 18 | 19 | ## Why Use Optional? 20 | 21 | * **Avoids NullPointerExceptions:** Enforces explicit handling of null values, reducing the risk of runtime errors. 22 | * **Improves Code Readability:** Makes it clear when a variable might be absent. 23 | * **Promotes Better Design:** Encourages developers to consider the absence of a value. 24 | 25 | ## Basic Concepts 26 | 27 | `Optional` can be thought of as a box that might or might not contain an object. Instead of returning `null`, a method can return an `Optional`. This forces the caller to explicitly check if a value is present. 28 | 29 | ## Creating Optional Objects 30 | 31 | There are several ways to create `Optional` objects: 32 | 33 | ### 1. `Optional.empty()` 34 | 35 | * Creates an empty `Optional` instance (i.e., it contains no value). 36 | 37 | ```java 38 | Optional emptyOptional = Optional.empty(); 39 | System.out.println(emptyOptional); // Output: Optional.empty 40 | ``` 41 | 42 | ### 2. `Optional.of(value)` 43 | 44 | * Creates an `Optional` with a non-null value. 45 | * Throws `NullPointerException` if the provided value is `null`. 46 | ```java 47 | String email = "test@example.com"; 48 | Optional emailOptional = Optional.of(email); 49 | System.out.println(emailOptional); // Output: Optional[test@example.com] 50 | 51 | String nullEmail = null; 52 | // Optional nullOptional = Optional.of(nullEmail); // Throws NullPointerException 53 | ``` 54 | 55 | ### 3. `Optional.ofNullable(value)` 56 | 57 | * Creates an `Optional` that can hold either a non-null value or `null`. 58 | * If the provided value is `null`, it creates an empty `Optional`. 59 | 60 | ```java 61 | String email = "test@example.com"; 62 | Optional emailOptional = Optional.ofNullable(email); 63 | System.out.println(emailOptional); // Output: Optional[test@example.com] 64 | 65 | String nullEmail = null; 66 | Optional nullOptional = Optional.ofNullable(nullEmail); 67 | System.out.println(nullOptional); // Output: Optional.empty 68 | ``` 69 | 70 | ## Working with Optional Values 71 | 72 | ### 1. `isPresent()` 73 | 74 | * Checks if a value is present in the `Optional`. 75 | * Returns `true` if a value is present, `false` otherwise. 76 | 77 | ```java 78 | Optional optionalValue = Optional.ofNullable("Hello"); 79 | if (optionalValue.isPresent()) { 80 | System.out.println("Value is present: " + optionalValue.get()); 81 | } else { 82 | System.out.println("Value is absent"); 83 | } 84 | ``` 85 | 86 | ### 2. `isEmpty()` (Java 11+) 87 | 88 | * Checks if the `Optional` is empty. 89 | * Returns `true` if empty, `false` otherwise. 90 | * The opposite of `isPresent()`. 91 | 92 | ```java 93 | Optional optionalValue = Optional.ofNullable(null); 94 | if (optionalValue.isEmpty()) { 95 | System.out.println("Value is absent"); 96 | } else { 97 | System.out.println("Value is present: " + optionalValue.get()); 98 | } 99 | ``` 100 | 101 | ### 3. `get()` 102 | 103 | * Retrieves the value from the `Optional`. 104 | * **Caution:** Throws `NoSuchElementException` if the `Optional` is empty. 105 | * **Avoid using `get()` without first checking with `isPresent()` or `isEmpty()`**. 106 | 107 | ```java 108 | Optional optionalValue = Optional.ofNullable("World"); 109 | if (optionalValue.isPresent()) { 110 | String value = optionalValue.get(); 111 | System.out.println(value); // Output: World 112 | } 113 | 114 | Optional emptyOptional = Optional.empty(); 115 | // String value = emptyOptional.get(); // Throws NoSuchElementException 116 | ``` 117 | 118 | ### 4. `orElse(defaultValue)` 119 | 120 | * Provides a default value to return if the `Optional` is empty. 121 | * The `defaultValue` is always evaluated, even if the `Optional` has a value. 122 | 123 | ```java 124 | Optional optionalValue = Optional.ofNullable(null); 125 | String value = optionalValue.orElse("Default Value"); 126 | System.out.println(value); // Output: Default Value 127 | ``` 128 | 129 | ### 5. `orElseGet(supplier)` 130 | 131 | * Provides a `Supplier` that generates a default value if the `Optional` is empty. 132 | * The `Supplier` is only invoked if the `Optional` is empty. 133 | * **Use `orElseGet()` when calculating the default value is expensive (e.g., involves a database call) to avoid unnecessary computation.** 134 | 135 | ```java 136 | Optional optionalValue = Optional.ofNullable(null); 137 | String value = optionalValue.orElseGet(() -> { 138 | // Perform expensive operation to get default value 139 | return "Default Value"; 140 | }); 141 | System.out.println(value); // Output: Default Value 142 | ``` 143 | 144 | ### 6. `orElseThrow(exceptionSupplier)` 145 | 146 | * Throws an exception if the `Optional` is empty. 147 | * The `exceptionSupplier` provides the exception to be thrown. 148 | 149 | ```java 150 | Optional optionalValue = Optional.ofNullable(null); 151 | String value = optionalValue.orElseThrow(() -> new IllegalArgumentException("Value is missing")); 152 | // Throws IllegalArgumentException: Value is missing 153 | ``` 154 | 155 | ### 7. `ifPresent(consumer)` 156 | 157 | * Performs an action with the value if it's present. 158 | * Takes a `Consumer` functional interface. 159 | 160 | ```java 161 | Optional optionalValue = Optional.ofNullable("Hello"); 162 | optionalValue.ifPresent(value -> System.out.println("Value: " + value)); // Output: Value: Hello 163 | 164 | Optional emptyOptional = Optional.empty(); 165 | emptyOptional.ifPresent(value -> System.out.println("This won't be printed")); 166 | ``` 167 | 168 | ### 8. `ifPresentOrElse(consumer, runnable)` (Java 9+) 169 | 170 | * Performs one of two actions based on whether a value is present or not. 171 | * Takes a `Consumer` for the present case and a `Runnable` for the empty case. 172 | 173 | ```java 174 | Optional optionalValue = Optional.ofNullable("Hello"); 175 | optionalValue.ifPresentOrElse( 176 | value -> System.out.println("Value is present: " + value), 177 | () -> System.out.println("Value is absent") 178 | ); // Output: Value is present: Hello 179 | 180 | Optional emptyOptional = Optional.ofNullable(null); 181 | emptyOptional.ifPresentOrElse( 182 | value -> System.out.println("Value is present: " + value), 183 | () -> System.out.println("Value is absent") 184 | ); // Output: Value is absent 185 | ``` 186 | 187 | ### 9. `filter(predicate)` 188 | 189 | * Filters the `Optional` value based on a `Predicate`. 190 | * If the value is present and matches the `Predicate`, it returns the `Optional`. 191 | * If the value is present but doesn't match, or if the `Optional` is empty, it returns an empty `Optional`. 192 | 193 | ```java 194 | Optional optionalValue = Optional.ofNullable(" abc "); 195 | Optional filteredValue = optionalValue.filter(value -> value.contains("abc")); 196 | filteredValue.ifPresent(value -> System.out.println("Filtered Value: " + value)); // Output: Filtered Value: abc 197 | 198 | Optional emptyOptional = Optional.ofNullable("def"); 199 | Optional filteredEmpty = emptyOptional.filter(value -> value.contains("xyz")); 200 | filteredEmpty.ifPresent(value -> System.out.println("This won't be printed")); 201 | ``` 202 | 203 | ### 10. `map(mapper)` 204 | 205 | * Transforms the value inside the `Optional` using a `Function`. 206 | * If the `Optional` is empty, it returns an empty `Optional`. 207 | 208 | ```java 209 | Optional optionalValue = Optional.ofNullable(" abc "); 210 | Optional trimmedValue = optionalValue.map(String::trim); 211 | trimmedValue.ifPresent(value -> System.out.println("Trimmed Value: " + value)); // Output: Trimmed Value: abc 212 | 213 | Optional emptyOptional = Optional.empty(); 214 | Optional mappedEmpty = emptyOptional.map(String::length); 215 | mappedEmpty.ifPresent(length -> System.out.println("This won't be printed")); 216 | ``` 217 | 218 | ### 11. `flatMap(mapper)` 219 | 220 | * Similar to `map()`, but the `mapper` function returns an `Optional`. 221 | * Useful for chaining `Optional` operations where nested Optionals might result. 222 | * Flattens the result to avoid `Optional>`. 223 | 224 | ## Code Examples and Best Practices 225 | 226 | ### Example: Handling Null Employee Data 227 | 228 | ```java 229 | class Employee { 230 | private Long id; 231 | private String firstName; 232 | private String lastName; 233 | private String email; 234 | private String address; 235 | private Long phoneNo; 236 | 237 | public String getEmail() { 238 | return email; 239 | } 240 | 241 | public Long getId() { 242 | return id; 243 | } 244 | } 245 | 246 | // Without Optional (prone to NullPointerException) 247 | Employee employee = getEmployee(); // May return null 248 | if (employee != null) { 249 | String email = employee.getEmail(); 250 | if (email != null) { 251 | String result = email.toLowerCase(); 252 | System.out.println(result); 253 | } 254 | } 255 | 256 | // With Optional (safer and cleaner) 257 | Optional optionalEmployee = Optional.ofNullable(getEmployee()); 258 | optionalEmployee.map(Employee::getEmail) 259 | .map(String::toLowerCase) 260 | .ifPresent(System.out::println); 261 | 262 | optionalEmployee.ifPresent(emp -> { 263 | Optional.ofNullable(emp.getId()).ifPresent(id -> { 264 | // Logic for handling employee id 265 | }); 266 | Optional.ofNullable(emp.getEmail()).ifPresent(email -> { 267 | // Logic for handling employee email 268 | }); 269 | }); 270 | ``` 271 | 272 | 273 | ### Example: Retrieving a Customer by Email 274 | ```java 275 | import java.util.List; 276 | import java.util.Optional; 277 | 278 | class Customer { 279 | private String email; 280 | 281 | public String getEmail() { 282 | return email; 283 | } 284 | 285 | public Customer(String email) { 286 | this.email = email; 287 | } 288 | } 289 | 290 | class EkartDataBase { 291 | private static List customers = List.of(new Customer("test@test.com")); 292 | 293 | public static List getALL() { 294 | return customers; 295 | } 296 | } 297 | 298 | public static Optional getCustomerByEmailId(String email) { 299 | return EkartDataBase.getALL().stream() 300 | .filter(customer -> customer.getEmail().equals(email)) 301 | .findAny(); 302 | } 303 | 304 | // Usage 305 | Optional customer = getCustomerByEmailId("test@test.com"); 306 | customer.ifPresentOrElse( 307 | c -> System.out.println("Customer found: " + c.getEmail()), 308 | () -> System.out.println("No customer found with that email") 309 | ); 310 | 311 | // Or throw an exception if not found 312 | Customer foundCustomer = getCustomerByEmailId("invalid@test.com") 313 | .orElseThrow(() -> new RuntimeException("No customer present with this email id")); 314 | ``` 315 | 316 | ### Example: Spring REST Controller 317 | ```java 318 | import org.springframework.http.HttpStatus; 319 | import org.springframework.http.ResponseEntity; 320 | import org.springframework.web.bind.annotation.GetMapping; 321 | import org.springframework.web.bind.annotation.PathVariable; 322 | import org.springframework.web.bind.annotation.RestController; 323 | 324 | import java.util.Optional; 325 | 326 | @RestController 327 | public class EmployeeController { 328 | 329 | private final EmployeeRepository repo; // Assume this is your repository 330 | 331 | public EmployeeController(EmployeeRepository repo) { 332 | this.repo = repo; 333 | } 334 | 335 | @GetMapping("/employees/{id}") 336 | public ResponseEntity getEmployeeById(@PathVariable Long id) { 337 | Optional employee = repo.findById(id); // Assuming findById returns Optional 338 | 339 | return employee.map(e -> ResponseEntity.ok(e)) 340 | .orElse(ResponseEntity.status(HttpStatus.NOT_FOUND) 341 | .body("Employee with ID " + id + " not found")); 342 | } 343 | 344 | @GetMapping("/employees/{id}/name") 345 | public ResponseEntity getEmployeeNameById(@PathVariable Long id) { 346 | Optional employee = repo.findById(id); 347 | 348 | return employee.flatMap(e -> Optional.ofNullable(e.getFirstName())) 349 | .map(name -> ResponseEntity.ok(name.toUpperCase())) 350 | .orElse(ResponseEntity.status(HttpStatus.NOT_FOUND) 351 | .body("Employee with ID " + id + " not found, or name is null")); 352 | } 353 | } 354 | ``` 355 | -------------------------------------------------------------------------------- /java-8/streams-example-employee-sample.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 🏢 Comprehensive Employee Examples 4 | 5 | This section demonstrates various stream operations applied specifically to a list of `Employee` objects, covering common data manipulation tasks. 6 | 7 | 8 | - [Iterating Over Employees](#iterating-over-employees) 9 | - [Collecting & Filtering Employee Data](#collecting--filtering-employee-data) 10 | - [Collect only the names of all employees into a new List.](#collect-only-the-names-of-all-employees-into-a-new-list) 11 | - [Filter employees older than 30.](#filter-employees-older-than-30) 12 | - [Find unique and duplicate employee names.](#find-unique-and-duplicate-employee-names) 13 | - [Store unique employee objs.](#store-unique-employee-objs) 14 | - [Store unique employee objs on the basis of -(key,value).](#store-unique-employee-objs-on-the-basis-of--keyvalue) 15 | - [Grouping Employees](#grouping-employees) 16 | - [Group employees by their Department.](#group-employees-by-their-department) 17 | - [Group employees by Active Status (Active vs. Inactive).](#group-employees-by-active-status-active-vs-inactive) 18 | - [Count employees in each Department.](#count-employees-in-each-department) 19 | - [Sorting Employees](#sorting-employees) 20 | - [Sort employees by Name in ascending order.](#sort-employees-by-name-in-ascending-order) 21 | - [Sort employees by Name in descending order.](#sort-employees-by-name-in-descending-order) 22 | - [Multi-level sorting: Sort by City Descending, then by Name Ascending.](#multi-level-sorting-sort-by-city-descending-then-by-name-ascending) 23 | - [Multi-level sorting: Sort by City Descending, then by Name Descending.](#multi-level-sorting-sort-by-city-descending-then-by-name-descending) 24 | - [Select the top 3 Employees with the highest Salaries.](#select-the-top-3-employees-with-the-highest-salaries) 25 | - [Select Employees starting from the 4th highest Salary onwards.](#select-employees-starting-from-the-4th-highest-salary-onwards) 26 | - [Select the 2nd & 3rd youngest Employees.](#select-the-2nd--3rd-youngest-employees) 27 | - [Employee Statistics](#-employee-statistics) 28 | - [Find the Employee with the Maximum Salary.](#find-the-employee-with-the-maximum-salary) 29 | - [Find the Employee with the Minimum Salary.](#find-the-employee-with-the-minimum-salary) 30 | - [Calculate Summary Statistics for Employee Ages (Count, Sum, Min, Average, Max).](#calculate-summary-statistics-for-employee-ages-count-sum-min-average-max) 31 | - [Find the Highest Salary in each Department.](#find-the-highest-salary-in-each-department) 32 | - [Stream Re-use Caveat](#-stream-re-use-caveat) 33 | - [Streams cannot be reused after a terminal operation is called.](#streams-cannot-be-reused-after-a-terminal-operation-is-called-attempting-to-do-so-results-in-an-illegalstateexception) 34 | - [To perform multiple operations, either recreate the stream or use a Supplier.](#to-perform-multiple-operations-either-recreate-the-stream-or-use-a-supplier) 35 | - [Conclusion](#-conclusion) 36 | 37 | 38 | 39 | --- 40 | ### Additional Resources 41 | 42 | If you found this guide helpful, you might also be interested in my other Spring Framework resources: 43 | - [Core Java & Java-8 Interview Questions](https://github.com/anilvn/Java-Interview-Questions/tree/main) 44 | - [Spring Boot Interview Questions](https://github.com/anilvn/spring-boot-interview-questions/tree/main) 45 | - [Microservices with Spring Cloud Tutorials](https://javatechonline.com/microservices-tutorial/) 46 | 47 | Feel free to star and fork these repositories if you find them useful! 48 | 49 | --- 50 | 51 | ### Employee Class Definition 52 | 53 | * _First, let's define the `Employee` class used in these examples._ 54 | ```java 55 | import java.util.Objects; 56 | 57 | class Employee { 58 | private String name; 59 | private int age; 60 | private String gender; 61 | private double salary; 62 | private String city; 63 | private String deptName; 64 | private boolean activeEmp; 65 | 66 | // Constructors , Getters, Setters , toStrring(), hashCode() 67 | 68 | @Override 69 | public boolean equals(Object o) { 70 | if (this == o) return true; 71 | if (o == null || getClass() != o.getClass()) return false; 72 | Employee employee = (Employee) o; 73 | return age == employee.age && Double.compare(employee.salary, salary) == 0 && 74 | activeEmp == employee.activeEmp && Objects.equals(name, employee.name) && 75 | Objects.equals(gender, employee.gender) && Objects.equals(city, employee.city) && 76 | Objects.equals(deptName, employee.deptName); 77 | } 78 | 79 | } 80 | ``` 81 | 82 | ### Sample Employee Data 83 | 84 | * _We'll use this list for the examples below._ 85 | ```java 86 | import java.util.Arrays; 87 | import java.util.List; 88 | import java.util.ArrayList; // Needed for some examples later 89 | 90 | List employeeList = Arrays.asList( 91 | new Employee("Alice", 30, "Female", 52000, "New York", "IT", true), 92 | new Employee("Bob", 25, "Male", 60000, "San Francisco", "Finance", false), 93 | new Employee("Charlie", 35, "Male", 55000, "New York", "Marketing", true), 94 | new Employee("David", 40, "Male", 70000, "San Francisco", "IT", true), 95 | new Employee("Emma", 28, "Female", 75000, "Los Angeles", "HR", false), 96 | new Employee("Frank", 35, "Male", 58000, "New York", "IT", true), // Duplicate name, same age as Charlie but diff salary 97 | new Employee("Grace", 28, "Female", 62000, "New York", "IT", true) // Same age as Emma 98 | ); 99 | ``` 100 | 101 | ### Iterating Over Employees 102 | 103 | * _Iterating using an enhanced for-loop (traditional)._ 104 | ```java 105 | System.out.println("--- Iterating with Enhanced For-Loop ---"); 106 | for (Employee emp : employeeList) { 107 | System.out.println(emp); 108 | // Access specific fields: System.out.println(emp.getName()); 109 | } 110 | ``` 111 | 112 | * _Iterating using `forEach` with a Lambda Expression._ 113 | ```java 114 | System.out.println("\n--- Iterating with forEach + Lambda ---"); 115 | employeeList.forEach(emp -> { 116 | System.out.println("Name: " + emp.getName() + ", Age: " + emp.getAge()); 117 | }); 118 | ``` 119 | 120 | * _Iterating using `forEach` with a Method Reference (prints the `toString()` representation)._ 121 | ```java 122 | System.out.println("\n--- Iterating with forEach + Method Reference ---"); 123 | employeeList.forEach(System.out::println); 124 | ``` 125 | 126 | * _Iterating using a Stream and `forEach` (equivalent to list's `forEach`)._ 127 | ```java 128 | System.out.println("\n--- Iterating with Stream + forEach ---"); 129 | employeeList.stream().forEach(emp -> { 130 | System.out.println("Dept: " + emp.getDeptName() + ", Salary: " + emp.getSalary()); 131 | }); 132 | ``` 133 | 134 | --- 135 | 136 | ### Collecting & Filtering Employee Data 137 | 138 | * _Collect only the names of all employees into a new List._ 139 | ```java 140 | import java.util.stream.Collectors; 141 | 142 | System.out.println("\n--- Collecting Employee Names ---"); 143 | List employeeNames = employeeList.stream() 144 | .map(Employee::getName) // Method reference for getter 145 | // .map(emp -> emp.getName()) // Equivalent lambda 146 | .collect(Collectors.toList()); 147 | System.out.println(employeeNames); 148 | ``` 149 | > _Output: `[Alice, Bob, Charlie, David, Emma, Frank, Grace]`_ 150 | 151 | * _Filter employees older than 30._ 152 | ```java 153 | System.out.println("\n--- Filtering Employees Older Than 30 ---"); 154 | List olderEmployees = employeeList.stream() 155 | .filter(emp -> emp.getAge() > 30) 156 | .collect(Collectors.toList()); 157 | olderEmployees.forEach(System.out::println); 158 | ``` 159 | > _Output: Includes Charlie, David, Frank_ 160 | 161 | * _Find unique and duplicate employee names._ 162 | ```java 163 | import java.util.Set; 164 | import java.util.HashSet; 165 | 166 | System.out.println("\n--- Finding Unique and Duplicate Names ---"); 167 | Set uniqueNames = new HashSet<>(); 168 | Set duplicateNames = employeeList.stream() 169 | .map(Employee::getName) 170 | .filter(name -> !uniqueNames.add(name)) // .add returns false if element already exists 171 | .collect(Collectors.toSet()); 172 | 173 | System.out.println("All Unique Names Encountered: " + uniqueNames); 174 | System.out.println("Duplicate Names Found: " + duplicateNames); 175 | ``` 176 | > _Output:_ 177 | > _All Unique Names Encountered: `[Alice, Bob, Charlie, David, Emma, Frank, Grace]` (order may vary)_ 178 | > _Duplicate Names Found: `[]` (In this specific dataset, names are unique)_ 179 | > _Note: If 'Frank' was named 'Charlie', Duplicates would be `[Charlie]`._ 180 | 181 |
182 | * _Store unique employee objs._ 183 | ```java 184 | Set uniqueEmployees = employeeList.stream() 185 | .collect(Collectors.toMap( 186 | e -> e.getId(), // Use employee ID as key 187 | Function.identity(), // Value: Employee object 188 | (e1, e2) -> e1 // If duplicate key (same ID), keep first 189 | )) 190 | .values() 191 | .stream() 192 | .collect(Collectors.toSet()); 193 | ``` 194 | 195 | * _Store unique employee objs on the basis of -(key,value)._ 196 | ```java 197 | // ✅ 1. Store first employee per department 198 | // If a department repeats, the first employee is retained, others are ignored 199 | Map firstEmployeeByDept = employeeList.stream() 200 | .collect(Collectors.toMap( 201 | Employee::getDeptName, // Key: department name 202 | e -> e, // Value: Employee object 203 | (existing, replacement) -> existing // Merge function: keep first (ignore replacement) 204 | )); 205 | 206 | System.out.println("=== First Employee per Department ==="); 207 | firstEmployeeByDept.forEach((dept, emp) -> 208 | System.out.println("Dept: " + dept + ", Employee: " + emp) 209 | ); 210 | 211 | // ✅ 2. Store latest employee per department 212 | // If a department repeats, the latest employee replaces the previous one 213 | Map latestEmployeeByDept = employeeList.stream() 214 | .collect(Collectors.toMap( 215 | Employee::getDeptName, // Key: department name 216 | e -> e, // Value: Employee object 217 | (existing, replacement) -> replacement // Merge function: keep latest (override existing) 218 | )); 219 | 220 | System.out.println("\n=== Latest Employee per Department ==="); 221 | latestEmployeeByDept.forEach((dept, emp) -> 222 | System.out.println("Dept: " + dept + ", Employee: " + emp) 223 | ); 224 | }); 225 | ``` 226 | 227 | ### 🧑‍🤝‍🧑 Grouping Employees 228 | 229 | * _Group employees by their Department._ 230 | ```java 231 | import java.util.Map; 232 | 233 | System.out.println("\n--- Grouping Employees by Department ---"); 234 | Map> employeesByDept = employeeList.stream() 235 | .collect(Collectors.groupingBy(Employee::getDeptName)); 236 | 237 | employeesByDept.forEach((dept, emps) -> { 238 | System.out.println("Department: " + dept); 239 | emps.forEach(emp -> System.out.println(" " + emp.getName())); 240 | }); 241 | ``` 242 | 243 | * _Group employees by Active Status (Active vs. Inactive)._ 244 | ```java 245 | System.out.println("\n--- Grouping Employees by Active Status ---"); 246 | Map> employeesByActiveStatus = employeeList.stream() 247 | .collect(Collectors.groupingBy(Employee::isActiveEmp)); 248 | 249 | employeesByActiveStatus.forEach((isActive, emps) -> { 250 | System.out.println("Active: " + isActive); 251 | emps.forEach(emp -> System.out.println(" " + emp.getName())); 252 | }); 253 | ``` 254 | 255 | 256 | * _Count employees in each Department._ 257 | ```java 258 | System.out.println("\n--- Counting Employees per Department ---"); 259 | Map countByDept = employeeList.stream() 260 | .collect(Collectors.groupingBy(Employee::getDeptName, // Group by department 261 | Collectors.counting())); // Count elements in each group 262 | countByDept.forEach((dept, count) -> System.out.println(dept + ": " + count)); 263 | ``` 264 | > _Output:_ 265 | > _HR: 1_ 266 | > _Finance: 1_ 267 | > _Marketing: 1_ 268 | > _IT: 4_ 269 | 270 | 271 | --- 272 | 273 | ### 📊 Sorting Employees 274 | 275 | 276 | * _Sort employees by Name in ascending order._ 277 | ```java 278 | // Approach 1: Using Collections.sort() with natural ordering 279 | Collections.sort(employees); // Uses compareTo() method 280 | 281 | // Approach 2: Alternative using Stream API 282 | List sortedEmployees = employees.stream() 283 | .sorted() // Uses natural ordering (compareTo) 284 | // .sorted(Comparator.comparing(Employee::getName) 285 | .collect(Collectors.toList()); 286 | 287 | // Approach 3:Sort employees by salary in ascending order using anonymous class. 288 | List sortedEmployees = employees.stream() 289 | .sorted(new Comparator() { 290 | @Override 291 | public int compare(Employee e1, Employee e2) { 292 | return Double.compare(e1.getSalary(), e2.getSalary()); // Better than casting 293 | } 294 | }) 295 | .collect(Collectors.toList()); 296 | 297 | // Approach 4: Using lambda expression 298 | List sorted3 = employees.stream() 299 | .sorted((e1, e2) -> e2.getName().compareTo(e1.getName())) 300 | .collect(Collectors.toList()); 301 | /* 302 | --------- Approach 5: Sorting using lambda and Double.compare --------- 303 | Safer than (e1.getSalary() - e2.getSalary()) 304 | because it avoids floating-point precision errors 305 | and potential overflow when working with large values. 306 | Returns: 307 | -1 if e1.getSalary() < e2.getSalary() 308 | 0 if equal 309 | 1 if e1.getSalary() > e2.getSalary() 310 | */ 311 | List sortedBySalary = employees.stream() 312 | .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())) // ascending order 313 | .collect(Collectors.toList()); 314 | ``` 315 | 316 | ``` 317 | Comparator.comparing(Employee::getName).reversed() 318 | Comparator.comparingInt(Employee::getId).reversed() 319 | Comparator.comparingDouble(Employee::getSalary).reversed() 320 | Comparator.comparingLong(Employee::getMobile).reversed() 321 | Comparator.comparing(Employee::getJoiningDate).reversed() - LocalDate 322 | ``` 323 | * _Sort employees by Name in descending order._ 324 | ```java 325 | // Approach 1: Using Collections.sort() with reverse order 326 | Collections.sort(employees, Collections.reverseOrder()); 327 | 328 | // Approach 2: Using Collections.reverseOrder() with method reference 329 | List sorted1 = employees.stream() 330 | .sorted(Comparator.comparing(Employee::getName).reversed()) 331 | .collect(Collectors.toList()); 332 | 333 | // Approach 3: Using anonymous comparator for descending order 334 | List sorted2 = employees.stream() 335 | .sorted(new Comparator() { 336 | @Override 337 | public int compare(Employee e1, Employee e2) { 338 | return e2.getName().compareTo(e1.getName()); // Reverse order 339 | } 340 | }) 341 | .collect(Collectors.toList()); 342 | 343 | // Approach 4: Using lambda expression 344 | List sorted3 = employees.stream() 345 | .sorted((e1, e2) -> e2.getName().compareTo(e1.getName())) 346 | .collect(Collectors.toList()); 347 | ``` 348 | 349 | * _Multi-level sorting: Sort by City Descending, then by Name Ascending.._ 350 | ```java 351 | List sortedEmployees = employees.stream() 352 | .sorted(Comparator.comparing(Employee::getCity).reversed() // City descending 353 | .thenComparing(Employee::getName)) // Then name ascending 354 | .collect(Collectors.toList()); 355 | 356 | ``` 357 | 358 | * _Multi-level sorting: Sort by City Descending, then by Name Descending.._ 359 | ```java 360 | List sortedEmployees = employees.stream() 361 | .sorted(Comparator.comparing(Employee::getCity).reversed() // City descending 362 | .thenComparing(Employee::getName).reversed()) // Then name descending 363 | .collect(Collectors.toList()); 364 | 365 | ``` 366 | 367 | * _Traditional approach for implementing the comparator interface method._ 368 | ```java 369 | class SalaryComparator implements Comparator { 370 | @Override 371 | public int compare(Employee e1, Employee e2) { 372 | return Double.compare(e1.getSalary(), e2.getSalary()); 373 | } 374 | } 375 | 376 | Collections.sort(employees, new SalaryComparator()); // Sorts in ascending order of salary 377 | 378 | ``` 379 | 380 | * _Select the top 3 Employees with the highest Salaries._ 381 | ```java 382 | System.out.println("\n--- Top 3 Highest Paid Employees ---"); 383 | List top3Salaries = employeeList.stream() 384 | .sorted(Comparator.comparingDouble(Employee::getSalary).reversed()) 385 | .limit(3) 386 | .collect(Collectors.toList()); 387 | top3Salaries.forEach(System.out::println); 388 | ``` 389 | 390 | * _Select Employees starting from the 4th highest Salary onwards._ 391 | ```java 392 | System.out.println("\n--- Employees After Top 3 Paid ---"); 393 | List afterTop3Salaries = employeeList.stream() 394 | .sorted(Comparator.comparingDouble(Employee::getSalary).reversed()) 395 | .skip(3) // Skip the first 3 396 | .collect(Collectors.toList()); 397 | afterTop3Salaries.forEach(System.out::println); 398 | ``` 399 | 400 | * _Select the 2nd & 3rd youngest Employees._ 401 | ```java 402 | System.out.println("\n--- 2nd and 3rd Youngest Employees ---"); 403 | List secondAndThirdYoungest = employeeList.stream() 404 | .sorted(Comparator.comparingInt(Employee::getAge)) 405 | .skip(1) // Skip the youngest 406 | .limit(2) // Take the next two 407 | .collect(Collectors.toList()); 408 | secondAndThirdYoungest.forEach(System.out::println); 409 | ``` 410 | > _Output: Includes Emma (28) and Grace (28)_ 411 | 412 | --- 413 | 414 | ### 📈 Employee Statistics 415 | 416 | * _Find the Employee with the Maximum Salary._ 417 | ```java 418 | System.out.println("\n--- Employee with Maximum Salary ---"); 419 | Optional highestPaidEmployee = employeeList.stream() 420 | .collect(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary))); 421 | // Alternatively: .max(Comparator.comparingDouble(Employee::getSalary)); 422 | highestPaidEmployee.ifPresent(System.out::println); 423 | ``` 424 | > _Output: Emma's record_ 425 | 426 | * _Find the Employee with the Minimum Salary._ 427 | ```java 428 | System.out.println("\n--- Employee with Minimum Salary ---"); 429 | Optional lowestPaidEmployee = employeeList.stream() 430 | .collect(Collectors.minBy(Comparator.comparingDouble(Employee::getSalary))); 431 | // Alternatively: .min(Comparator.comparingDouble(Employee::getSalary)); 432 | lowestPaidEmployee.ifPresent(System.out::println); 433 | ``` 434 | > _Output: Alice's record_ 435 | 436 | * _Calculate Summary Statistics for Employee Ages (Count, Sum, Min, Average, Max)._ 437 | ```java 438 | import java.util.IntSummaryStatistics; 439 | 440 | System.out.println("\n--- Summary Statistics for Employee Ages ---"); 441 | IntSummaryStatistics ageStats = employeeList.stream() 442 | .mapToInt(Employee::getAge) // Convert to IntStream 443 | // .mapToDouble(Employee::getSalary) // Convert to DoubleStream - for the salaryStats 444 | .summaryStatistics(); // Calculate stats 445 | 446 | System.out.println("Count: " + ageStats.getCount()); 447 | System.out.println("Sum: " + ageStats.getSum()); 448 | System.out.println("Min: " + ageStats.getMin()); 449 | System.out.println("Average: " + ageStats.getAverage()); 450 | System.out.println("Max: " + ageStats.getMax()); 451 | ``` 452 | > _Output:_ 453 | > _Count: 7_ 454 | > _Sum: 221_ 455 | > _Min: 25_ 456 | > _Average: 31.57..._ 457 | > _Max: 40_ 458 | 459 | 460 | * _Find the Highest Salary in each Department._ 461 | ```java 462 | import java.util.function.BinaryOperator; 463 | 464 | System.out.println("\n--- Highest Salary per Department ---"); 465 | Map> highestSalaryByDept = employeeList.stream() 466 | .collect(Collectors.groupingBy( 467 | Employee::getDeptName, 468 | Collectors.reducing(BinaryOperator.maxBy(Comparator.comparingDouble(Employee::getSalary))) 469 | )); 470 | 471 | highestSalaryByDept.forEach((dept, empOpt) -> { 472 | System.out.print("Dept: " + dept + ", Highest Paid: "); 473 | empOpt.ifPresent(emp -> System.out.println(emp.getName() + " (" + emp.getSalary() + ")")); 474 | }); 475 | ``` 476 | 477 | --- 478 | 479 | ### ⚠️ Stream Re-use Caveat 480 | 481 | * _Streams cannot be reused after a terminal operation is called. Attempting to do so results in an `IllegalStateException`._ 482 | ```java 483 | Stream namesStream = employeeList.stream().map(Employee::getName); 484 | System.out.println("\n--- Stream Re-use Attempt ---"); 485 | System.out.println("First consumption (forEach):"); 486 | namesStream.forEach(System.out::println); // Consumes the stream 487 | 488 | try { 489 | // Attempting to reuse the *same* stream instance 490 | long count = namesStream.count(); // This will fail 491 | System.out.println("Count (should not be reached): " + count); 492 | } catch (IllegalStateException e) { 493 | System.out.println("Error trying to reuse stream: " + e.getMessage()); 494 | } 495 | ``` 496 | > _Output: Will print names, then throw `IllegalStateException: stream has already been operated upon or closed`_ 497 | 498 | * _To perform multiple operations, either recreate the stream or use a `Supplier`._ 499 | ```java 500 | import java.util.function.Supplier; 501 | 502 | // Option 1: Recreate the stream 503 | System.out.println("\n--- Recreating Stream ---"); 504 | employeeList.stream().map(Employee::getName).forEach(System.out::println); 505 | long countRecreated = employeeList.stream().map(Employee::getName).count(); 506 | System.out.println("Count (recreated): " + countRecreated); 507 | 508 | // Option 2: Use a Supplier 509 | System.out.println("\n--- Using Supplier for Stream ---"); 510 | Supplier> employeeStreamSupplier = () -> employeeList.stream(); 511 | 512 | System.out.println("First consumption via supplier:"); 513 | employeeStreamSupplier.get().map(Employee::getName).forEach(System.out::println); // Gets a new stream 514 | 515 | System.out.println("Second consumption via supplier:"); 516 | long countSupplier = employeeStreamSupplier.get().count(); // Gets another new stream 517 | System.out.println("Count (supplier): " + countSupplier); 518 | ``` 519 | 520 | --- 521 | 522 | ## ✅ Conclusion 523 | 524 | > Java Streams offer a flexible and expressive paradigm for data processing. Mastering the distinction between **lazy intermediate operations** and **eager terminal operations**, along with understanding how to chain them effectively, unlocks the power of the Stream API for writing clean, declarative, and efficient Java code. 525 | 526 | > Common problems, especially when working with collections of objects like `Employee`, can often be solved elegantly using combinations of stream operations like `filter`, `map`, `reduce`, `collect` (especially `groupingBy`), `sorted`, `distinct`, and summary statistics methods. Remember the single-consumption nature of streams and plan accordingly for multiple operations. 527 | -------------------------------------------------------------------------------- /multi-threading/multithreading-simplified-notes.md: -------------------------------------------------------------------------------- 1 | # Table of Contents for Java Multithreading Notes 2 | 3 | Based on the provided document, here is a detailed table of contents for the Java multithreading content: 4 | 5 | ## 1. Main Thread Execution 6 | - Program demonstrating main thread execution with static and non-static variables and methods 7 | - Execution order of static and non-static initializations 8 | 9 | ## 2. User-Defined Threads 10 | - Steps to create user-defined threads in Java 11 | - Ways to define user-defined threads 12 | - Extending java.lang.Thread class 13 | - Implementing java.lang.Runnable interface 14 | - Example programs for user-defined threads 15 | - Thread naming and identification 16 | 17 | ## 3. Thread Chaining 18 | - Program demonstrating thread chaining concept 19 | - Method calling within thread execution context 20 | 21 | ## 4. Multiple Thread Execution 22 | - Creating and executing multiple user-defined threads 23 | - Thread execution using Thread class 24 | - Thread execution using Runnable interface 25 | - Thread scheduling and execution order 26 | 27 | ## 5. Thread Synchronization 28 | - Concept of synchronization in Java 29 | - Program demonstrating synchronization with Institute class example 30 | - Synchronized methods vs synchronized blocks 31 | - Thread access control for shared resources 32 | - Effect of synchronization on thread execution 33 | 34 | ## 6. Thread Lifecycle 35 | - Different states in thread lifecycle 36 | - Program demonstrating thread lifecycle 37 | - IllegalThreadStateException when starting a thread twice 38 | 39 | ## 7. Thread Control Methods 40 | - Thread.sleep() method 41 | - Purpose and usage 42 | - Example programs with sleep() 43 | - join() method 44 | - Purpose and usage 45 | - Example programs with join() 46 | - Creating deadlock scenarios using join() 47 | - wait(), notify(), and notifyAll() methods 48 | - Inter-thread communication 49 | - Example program with banking transaction 50 | 51 | ## 8. Thread Priority 52 | - Daemon vs Non-Daemon threads 53 | - Low Priority Threads (LPT) vs High Priority Threads (HPT) 54 | - isDaemon() method usage 55 | - setDaemon() method for changing thread priority 56 | - Relationship between thread types and lifecycle 57 | 58 | ## 9. Additional Thread Control Methods 59 | - yield() method 60 | - Purpose and usage 61 | - Example with producer-consumer scenario 62 | - interrupt() method 63 | - Purpose and usage 64 | - Handling thread interruption 65 | 66 | ## 10. Thread Groups 67 | - Creating and managing thread groups 68 | - Parent and child thread groups 69 | - Thread group properties and methods 70 | - Setting priority for thread groups 71 | - Monitoring active threads in a group 72 | 73 | ## 11. Modern Thread Creation 74 | - Using lambda expressions with Runnable interface 75 | - Simplified thread creation in modern Java 76 | 77 | Each section contains explanatory text and example code demonstrating the concepts, with annotations about the expected output and behavior of the programs. 78 | 79 | --- 80 | # Java Multithreading: Comprehensive Notes 81 | 82 | ## 1. Main Thread Execution 83 | 84 | The `Thread.currentThread()` method returns a reference to the currently executing thread. When Java application starts, the main thread is automatically created and begins execution. 85 | 86 | ```java 87 | // Execution order for class with static and non-static elements 88 | // Order: Static variables/blocks → Main method → Non-static variables/blocks → Constructor 89 | class Test { 90 | static int a = m1(); // 1. Static variable initialization 91 | static { /* Static block */} // 2. Static block execution 92 | int b = m2(); // 4. Non-static variable initialization 93 | { /* Non-static block */ } // 5. Non-static block execution 94 | Test() { /* Constructor */ } // 6. Constructor execution 95 | 96 | public static void main() { // 3. Main method execution 97 | Test t = new Test(); // Creates instance, triggering 4, 5, 6 98 | } 99 | } 100 | ``` 101 | 102 | ## 2. User-Defined Threads 103 | 104 | There are two ways to create custom threads in Java: 105 | 106 | ### Extending Thread class 107 | ```java 108 | class MyThread extends Thread { 109 | @Override 110 | public void run() { 111 | // Thread code goes here 112 | } 113 | } 114 | 115 | // Usage 116 | MyThread thread = new MyThread(); 117 | thread.start(); // Not thread.run() - this would execute in the current thread 118 | ``` 119 | 120 | ### Implementing Runnable interface 121 | ```java 122 | class MyRunnable implements Runnable { 123 | @Override 124 | public void run() { 125 | // Thread code goes here 126 | } 127 | } 128 | 129 | // Usage 130 | Thread thread = new Thread(new MyRunnable()); 131 | thread.start(); 132 | ``` 133 | 134 | Modern Java allows for lambda expressions with Runnable: 135 | ```java 136 | Thread thread = new Thread(() -> { 137 | // Thread code goes here 138 | }); 139 | thread.start(); 140 | ``` 141 | 142 | ## 3. Thread Control Methods 143 | 144 | ### sleep() 145 | Pauses thread execution for specified milliseconds: 146 | ```java 147 | try { 148 | Thread.sleep(1000); // Sleep for 1 second 149 | } catch (InterruptedException e) { 150 | e.printStackTrace(); 151 | } 152 | ``` 153 | 154 | ### join() 155 | Waits for another thread to complete before continuing: 156 | ```java 157 | Thread thread = new Thread(() -> { 158 | // Some operations 159 | }); 160 | thread.start(); 161 | 162 | try { 163 | thread.join(); // Current thread waits for thread to finish 164 | } catch (InterruptedException e) { 165 | e.printStackTrace(); 166 | } 167 | ``` 168 | 169 | ### yield() 170 | Suggests that the current thread is willing to yield its execution: 171 | ```java 172 | Thread.yield(); // Hint to scheduler that other threads can run 173 | ``` 174 | 175 | ### interrupt() 176 | Interrupts a thread, typically used to stop long-running or blocked threads: 177 | ```java 178 | Thread thread = new Thread(() -> { 179 | try { 180 | Thread.sleep(10000); 181 | } catch (InterruptedException e) { 182 | // Handle interruption 183 | } 184 | }); 185 | thread.start(); 186 | thread.interrupt(); // Interrupt the thread 187 | ``` 188 | 189 | ## 4. Thread Synchronization 190 | 191 | Synchronization controls access to shared resources, allowing only one thread to access at a time. 192 | 193 | ### Synchronized Methods 194 | ```java 195 | public class Counter { 196 | private int count = 0; 197 | 198 | synchronized public void increment() { 199 | count++; 200 | } 201 | 202 | synchronized public int getCount() { 203 | return count; 204 | } 205 | } 206 | ``` 207 | 208 | ### Synchronized Blocks 209 | ```java 210 | public void increment() { 211 | synchronized(this) { 212 | count++; 213 | } 214 | } 215 | ``` 216 | 217 | ## 5. Inter-Thread Communication 218 | 219 | The `wait()`, `notify()` and `notifyAll()` methods enable communication between threads: 220 | 221 | ```java 222 | class SharedResource { 223 | private boolean dataProduced = false; 224 | private int data; 225 | 226 | synchronized public void produce(int value) { 227 | while (dataProduced) { 228 | try { 229 | wait(); // Wait until consumer consumes 230 | } catch (InterruptedException e) { 231 | Thread.currentThread().interrupt(); 232 | } 233 | } 234 | 235 | data = value; 236 | dataProduced = true; 237 | notify(); // Notify consumer 238 | } 239 | 240 | synchronized public int consume() { 241 | while (!dataProduced) { 242 | try { 243 | wait(); // Wait until producer produces 244 | } catch (InterruptedException e) { 245 | Thread.currentThread().interrupt(); 246 | } 247 | } 248 | 249 | dataProduced = false; 250 | notify(); // Notify producer 251 | return data; 252 | } 253 | } 254 | ``` 255 | 256 | ## 6. Thread Priority 257 | 258 | Threads can be classified as daemon (low priority) or non-daemon (high priority): 259 | 260 | ```java 261 | Thread thread = new Thread(() -> { 262 | // Code 263 | }); 264 | thread.setDaemon(true); // Set as daemon thread 265 | thread.start(); 266 | 267 | boolean isDaemon = thread.isDaemon(); // Check if thread is daemon 268 | ``` 269 | 270 | - Daemon threads automatically terminate when all non-daemon threads finish 271 | - JVM will not wait for daemon threads to complete before exiting 272 | 273 | ## 7. Thread Groups 274 | 275 | Thread groups organize and manage related threads: 276 | 277 | ```java 278 | ThreadGroup parentGroup = new ThreadGroup("Parent"); 279 | ThreadGroup childGroup = new ThreadGroup(parentGroup, "Child"); 280 | 281 | Thread thread1 = new Thread(parentGroup, () -> { 282 | // Thread code 283 | }, "Thread1"); 284 | 285 | parentGroup.setMaxPriority(7); // Set max priority for all threads in group 286 | int activeCount = parentGroup.activeCount(); // Get number of active threads 287 | ``` 288 | 289 | ## 8. Deadlock Prevention 290 | 291 | Deadlocks occur when two or more threads are blocked forever, waiting for each other: 292 | 293 | ```java 294 | // Potential deadlock scenario 295 | Thread t1 = new Thread(() -> { 296 | synchronized(resourceA) { 297 | // Do something 298 | synchronized(resourceB) { 299 | // Do something 300 | } 301 | } 302 | }); 303 | 304 | Thread t2 = new Thread(() -> { 305 | synchronized(resourceB) { 306 | // Do something 307 | synchronized(resourceA) { 308 | // Do something 309 | } 310 | } 311 | }); 312 | ``` 313 | 314 | Prevention techniques: 315 | 1. Lock ordering: Always acquire locks in the same order 316 | 2. Lock timeouts: Use `tryLock()` with timeout 317 | 3. Deadlock detection: Use tools to detect potential deadlocks 318 | 319 | ## Best Practices 320 | 321 | 1. Prefer implementing `Runnable` over extending `Thread` 322 | 2. Keep synchronization blocks as small as possible 323 | 3. Avoid calling thread control methods in synchronized blocks 324 | 4. Use thread pools instead of creating threads manually 325 | 5. Use high-level concurrency utilities from `java.util.concurrent` package 326 | 6. Handle InterruptedException properly 327 | 7. Be careful with thread priority - it's platform dependent 328 | 8. Avoid thread.stop(), thread.suspend(), thread.resume() - they are deprecated 329 | 330 | ## Common Issues 331 | 332 | 1. Race conditions: Multiple threads accessing shared data concurrently 333 | 2. Deadlocks: Two or more threads waiting for each other indefinitely 334 | 3. Starvation: Thread never gets access to resources 335 | 4. Livelock: Threads respond to each other but make no progress 336 | 5. Over-synchronization: Excessive locking reduces concurrency 337 | 338 | Remember that thread scheduling is non-deterministic and depends on JVM implementation and operating system. --------------------------------------------------------------------------------