0% found this document useful (0 votes)
0 views36 pages

Java Master Handbook Section3 AdvancedJava

The document is a comprehensive guide on advanced Java topics, including exception handling, file I/O, generics, and more. It covers key concepts such as exception hierarchy, checked vs unchecked exceptions, file operations, and the use of generics for type safety. Additionally, it provides best practices and interview questions related to these advanced topics.

Uploaded by

Rajiv Sharma
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views36 pages

Java Master Handbook Section3 AdvancedJava

The document is a comprehensive guide on advanced Java topics, including exception handling, file I/O, generics, and more. It covers key concepts such as exception hierarchy, checked vs unchecked exceptions, file operations, and the use of generics for type safety. Additionally, it provides best practices and interview questions related to these advanced topics.

Uploaded by

Rajiv Sharma
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

JAVA MASTER HANDBOOK | Section 3: Advanced Java

JAVA MASTER HANDBOOK


Section 3: Advanced Java
Exception Handling · File I/O · Generics · Annotations · Reflection · Lambdas · Streams · Optional · Date-
Time API · Java 8–21 Features

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Page 1
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 1: Exception Handling

1.1 What is an Exception?


An exception is an unwanted or unexpected event that occurs during program execution and disrupts
the normal flow of instructions. Java provides a robust exception handling framework to detect, catch,
and recover from errors gracefully.
Real-world analogy: A GPS navigation app has a planned route (normal flow). If there is a road closure
(exception), the app doesn't crash — it reroutes you (handles the exception) and continues navigating.

1.2 Exception Hierarchy


Java Exception Class Hierarchy
[Link]
├── [Link] ← JVM errors, do NOT catch
│ ├── OutOfMemoryError
│ ├── StackOverflowError
│ └── VirtualMachineError
└── [Link] ← Handle these
├── RuntimeException ← Unchecked (compiler doesn't enforce)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── ClassCastException
│ ├── IllegalArgumentException
│ ├── ArithmeticException
│ └── NumberFormatException
├── IOException ← Checked
├── SQLException ← Checked
└── ClassNotFoundException ← Checked

1.3 Checked vs Unchecked Exceptions


Aspect Checked vs Unchecked
Checked Exception Compiler forces you to handle or declare. Extends Exception (not
RuntimeException). Example: IOException, SQLException,
FileNotFoundException.
Unchecked Exception Compiler does NOT enforce. Extends RuntimeException. Example:
NullPointerException, ArrayIndexOutOfBoundsException.
Error JVM-level failures. Never catch. Example: OutOfMemoryError,
StackOverflowError.
When to use Checked Recoverable conditions the caller should handle: file not found,
network timeout.
When to use Unchecked Programming errors: null dereference, bad array index, invalid cast.

Page 2
JAVA MASTER HANDBOOK | Section 3: Advanced Java

1.4 try-catch-finally
public class ExceptionDemo {
public static void main(String[] args) {
// Basic try-catch
try {
int result = 10 / 0; // Throws ArithmeticException
[Link](result); // Never executes
} catch (ArithmeticException e) {
[Link]("Caught: " + [Link]()); // / by zero
}

// Multiple catch blocks (most specific first)


try {
String s = null;
[Link](); // NullPointerException
} catch (NullPointerException e) {
[Link]("Null reference: " + [Link]());
} catch (RuntimeException e) {
[Link]("Runtime error"); // Less specific — comes after
} catch (Exception e) {
[Link]("General error"); // Most general — last
}

// Multi-catch (Java 7+) — same handler for multiple types


try {
String[] arr = {"1", "two", "3"};
int n = [Link](arr[5]); // Could be AIOOBE or NFE
} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
[Link]("Caught multi: " + [Link]().getSimpleName());
}

// finally — ALWAYS executes (even if exception or return)


[Link]("Finally demo: " + divide(10, 0));
}

static String divide(int a, int b) {


try {
return [Link](a / b);
} catch (ArithmeticException e) {
return "Error: " + [Link]();
} finally {
[Link]("finally block always runs");
// WARNING: returning from finally overrides try/catch return
// Don't do: return "from finally"; — it swallows exceptions!
}
}
}

1.5 throw and throws


// throws — declares that a method MAY throw a checked exception
// Callers must handle or re-declare
public String readFile(String path) throws IOException, FileNotFoundException {
if (path == null) throw new IllegalArgumentException("Path cannot be null");
// ... file reading code
return content;
}

// throw — actually throws an exception object


public void setAge(int age) {

Page 3
JAVA MASTER HANDBOOK | Section 3: Advanced Java

if (age < 0 || age > 150)


throw new IllegalArgumentException("Invalid age: " + age);
[Link] = age;
}

// Re-throwing — catch, log, and re-throw


public void processData(String data) throws DataProcessingException {
try {
// risky operation
} catch (IOException e) {
[Link]("Failed to process data", e);
throw new DataProcessingException("Processing failed", e); // wrap
}
}

1.6 try-with-resources (Java 7+)


// Resources that implement AutoCloseable are automatically closed
// No need for finally block to close streams

// OLD WAY (verbose, error-prone)


BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("[Link]"));
String line = [Link]();
} catch (IOException e) {
[Link]();
} finally {
if (br != null) try { [Link](); } catch (IOException e) { }
}

// NEW WAY — try-with-resources (Java 7+)


try (BufferedReader br = new BufferedReader(new FileReader("[Link]"));
PrintWriter pw = new PrintWriter(new FileWriter("[Link]"))) {
String line;
while ((line = [Link]()) != null) {
[Link]([Link]());
}
} catch (IOException e) {
[Link]("IO Error: " + [Link]());
}
// Both br and pw are automatically closed in reverse order of declaration
// Even if an exception occurs mid-way

// Custom AutoCloseable:
class DatabaseConnection implements AutoCloseable {
public DatabaseConnection() { [Link]("Connecting..."); }
public void query(String sql) { [Link]("Running: " + sql); }
@Override public void close() { [Link]("Connection closed"); }
}

try (DatabaseConnection conn = new DatabaseConnection()) {


[Link]("SELECT * FROM users");
} // close() called automatically here

1.7 Custom Exceptions


// Checked custom exception

Page 4
JAVA MASTER HANDBOOK | Section 3: Advanced Java

public class InsufficientFundsException extends Exception {


private double amount;
private double balance;

public InsufficientFundsException(double amount, double balance) {


super([Link]("Cannot withdraw %.2f. Balance: %.2f", amount,
balance));
[Link] = amount;
[Link] = balance;
}

// Constructor with cause (for exception chaining)


public InsufficientFundsException(String message, Throwable cause) {
super(message, cause);
}

public double getAmount() { return amount; }


public double getBalance() { return balance; }
}

// Unchecked custom exception


public class InvalidOrderException extends RuntimeException {
private String orderId;

public InvalidOrderException(String orderId, String reason) {


super("Order " + orderId + " is invalid: " + reason);
[Link] = orderId;
}
public String getOrderId() { return orderId; }
}

// Usage:
class BankAccount {
private double balance;
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance)
throw new InsufficientFundsException(amount, balance);
balance -= amount;
}
}

try {
[Link](5000);
} catch (InsufficientFundsException e) {
[Link]([Link]());
[Link]("Tried: %.2f, Have: %.2f%n", [Link](), [Link]());
}

1.8 Exception Best Practices


• Always catch the most specific exception first, general last.
• Never swallow exceptions silently: catch(Exception e) {} — always log or rethrow.
• Use try-with-resources for any resource that implements AutoCloseable.
• Prefer unchecked exceptions for programming errors; checked for recoverable conditions.
• Include meaningful messages and relevant context in exception constructors.
• Use exception chaining (new RuntimeException("msg", originalCause)) to preserve root cause.
• Don't use exceptions for normal control flow — they are expensive.
• Document thrown exceptions with @throws Javadoc on public API methods.

Page 5
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Interview Questions
1. What is the difference between checked and unchecked exceptions?
2. What is the difference between throw and throws?
3. Can finally block be skipped? When?
4. What is try-with-resources? What interface must a resource implement?
5. What happens if both catch and finally throw exceptions?
6. What is exception chaining / exception wrapping?
7. What is the difference between Error and Exception?
8. Can we have try without catch? Can we have try without finally?
9. What is a multi-catch block (Java 7+)?
10. When should you create a custom exception?

Page 6
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 2: File Handling

2.1 File Class


import [Link];

File file = new File("data/[Link]");

// File info
[Link](); // true/false
[Link](); // "[Link]"
[Link](); // "data/[Link]"
[Link](); // full path from root
[Link](); // size in bytes
[Link](); // true if it's a file
[Link](); // true if it's a directory
[Link](); // timestamp in ms

// File operations
[Link](); // Creates the file
[Link](); // Deletes file
[Link](); // Creates single directory
[Link](); // Creates all missing parent dirs
[Link](new File("[Link]")); // Rename/move

// List directory contents


File dir = new File("src");
String[] names = [Link](); // Array of names
File[] files = [Link](); // Array of File objects

// Filter files
File[] javaFiles = [Link](f -> [Link]().endsWith(".java"));

2.2 Reading Files


import [Link].*;
import [Link].*;

// ── Method 1: BufferedReader (line by line, efficient) ──


try (BufferedReader br = new BufferedReader(new FileReader("[Link]"))) {
String line;
while ((line = [Link]()) != null) {
[Link](line);
}
}

// ── Method 2: Scanner (convenient for tokens) ──


try (Scanner sc = new Scanner(new File("[Link]"))) {
[Link](",|\n");
while ([Link]()) {
[Link]([Link]() + " | ");
}
}

// ── Method 3: NIO Files (Java 7+, simplest for small files) ──


// Read all lines at once

Page 7
JAVA MASTER HANDBOOK | Section 3: Advanced Java

List<String> lines = [Link]([Link]("[Link]"));


[Link]([Link]::println);

// Read as one String


String content = [Link]([Link]("[Link]")); // Java 11+

// Read as byte array


byte[] bytes = [Link]([Link]("[Link]"));

// ── Method 4: Stream of lines (lazy, best for large files) ──


try (Stream<String> stream = [Link]([Link]("[Link]"))) {
long errorCount = stream
.filter(l -> [Link]("ERROR"))
.count();
[Link]("Errors: " + errorCount);
}

2.3 Writing Files


// ── Method 1: BufferedWriter (efficient, line by line) ──
try (BufferedWriter bw = new BufferedWriter(new FileWriter("[Link]"))) {
[Link]("Line 1");
[Link]();
[Link]("Line 2");
}

// Append to existing file: FileWriter("[Link]", true)


try (BufferedWriter bw = new BufferedWriter(new FileWriter("[Link]", true))) {
[Link]("[" + [Link]() + "] Application started");
[Link]();
}

// ── Method 2: PrintWriter (formatted output) ──


try (PrintWriter pw = new PrintWriter(new FileWriter("[Link]"))) {
[Link]("%-20s %10s%n", "Product", "Price");
[Link]("%-20s %10.2f%n", "Laptop", 75000.0);
[Link]("%-20s %10.2f%n", "Mouse", 999.0);
}

// ── Method 3: NIO Files (Java 7+) ──


[Link]([Link]("[Link]"), "Hello NIO".getBytes());
[Link]([Link]("[Link]"), "Hello NIO"); // Java 11+
[Link]([Link]("[Link]"), [Link]("Line1", "Line2", "Line3"));

// Append with NIO:


[Link]([Link]("[Link]"), [Link]("new entry"),
[Link], [Link]);

2.4 Serialization & Deserialization


import [Link].*;

// Serializable marks a class as safe to convert to byte stream


public class Employee implements Serializable {
private static final long serialVersionUID = 1L; // Version control
private String name;
private int empId;

Page 8
JAVA MASTER HANDBOOK | Section 3: Advanced Java

private transient String password; // transient: NOT serialized


private static int count; // static: NOT serialized (belongs to
class)

public Employee(String name, int empId, String password) {


[Link]=name; [Link]=empId; [Link]=password;
}
public String toString() {
return "Employee{id=" + empId + ", name=" + name + ", pwd=" + password +
"}";
}
}

// SERIALIZE — write object to file


try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("[Link]"))) {
Employee emp = new Employee("Alice", 101, "secret123");
[Link](emp);
[Link]("Serialized: " + emp);
}

// DESERIALIZE — read object from file


try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("[Link]"))) {
Employee restored = (Employee) [Link]();
[Link]("Deserialized: " + restored);
// Output: Employee{id=101, name=Alice, pwd=null}
// password is null because it was transient!
}

Interview Questions
11. What is the difference between FileReader and BufferedReader?
12. What is serialization? What interface is required?
13. What is serialVersionUID and why is it important?
14. What does the transient keyword do during serialization?
15. What is the difference between FileOutputStream and ObjectOutputStream?
16. How do you append to a file in Java?
17. What are NIO Files advantages over classic IO?
18. Can static variables be serialized?

Page 9
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 3: Generics

3.1 What are Generics?


Generics allow you to write type-safe, reusable code by parameterizing types. Instead of working with
raw Object types and casting, generics let the compiler enforce type correctness at compile time.
Real-world analogy: A box (generic class Box<T>) can hold anything — a book, a toy, or a phone.
When you create a 'Box for Books', you can only put books in it and you always get a book out, no
casting needed.

// WITHOUT generics (old way — type-unsafe)


List list = new ArrayList();
[Link]("Hello");
[Link](42); // No compile error — accepts anything
String s = (String) [Link](0); // Must cast — can throw ClassCastException

// WITH generics (type-safe)


List<String> names = new ArrayList<>();
[Link]("Alice");
[Link]("Bob");
// [Link](42); // COMPILE ERROR — type enforced!
String name = [Link](0); // No cast needed — compiler knows it's a String

3.2 Generic Classes


// Generic class with type parameter T
public class Pair<K, V> {
private K key;
private V value;

public Pair(K key, V value) {


[Link] = key;
[Link] = value;
}

public K getKey() { return key; }


public V getValue() { return value; }

@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}

// Usage — different type combinations


Pair<String, Integer> nameAge = new Pair<>("Alice", 30);
Pair<String, String> cityCountry = new Pair<>("Mumbai", "India");
Pair<Integer, Double> idSalary = new Pair<>(101, 75000.0);

[Link](nameAge); // (Alice, 30)


[Link](cityCountry); // (Mumbai, India)

// Generic Stack implementation

Page 10
JAVA MASTER HANDBOOK | Section 3: Advanced Java

public class Stack<T> {


private List<T> elements = new ArrayList<>();

public void push(T item) { [Link](item); }


public T pop() {
if (isEmpty()) throw new EmptyStackException();
return [Link]([Link]() - 1);
}
public T peek() { return [Link]([Link]() - 1); }
public boolean isEmpty() { return [Link](); }
public int size() { return [Link](); }
}

Stack<String> stack = new Stack<>();


[Link]("Java");
[Link]("Python");
[Link]([Link]()); // Python

3.3 Generic Methods


public class GenericUtils {

// Generic method — <T> declared before return type


public static <T> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

// Generic method returning a value


public static <T> T getMiddle(T[] arr) {
return arr[[Link] / 2];
}

// Multiple type parameters


public static <K, V> Map<V, K> invertMap(Map<K, V> original) {
Map<V, K> inverted = new HashMap<>();
for ([Link]<K, V> entry : [Link]()) {
[Link]([Link](), [Link]());
}
return inverted;
}
}

String[] words = {"Java", "Generics", "Demo"};


[Link](words, 0, 2);
[Link]([Link](words)); // [Demo, Generics, Java]

[Link]([Link](words)); // Generics

3.4 Bounded Type Parameters


// Upper bound: T must be Number or a subtype of Number
public static <T extends Number> double sum(List<T> list) {
double total = 0;
for (T item : list) {
total += [Link](); // Can call Number methods

Page 11
JAVA MASTER HANDBOOK | Section 3: Advanced Java

}
return total;
}

[Link](sum([Link](1, 2, 3))); // 6.0 (Integer extends Number)


[Link](sum([Link](1.5, 2.5, 3.0))); // 7.0 (Double extends Number)
// sum([Link]("a","b")); // COMPILE ERROR — String doesn't extend Number

// Multiple bounds: T extends Number AND implements Comparable


public static <T extends Number & Comparable<T>> T max(T a, T b) {
return [Link](b) >= 0 ? a : b;
}

[Link](max(10, 20)); // 20
[Link](max(3.14, 2.71)); // 3.14

3.5 Wildcards
// ? — unbounded wildcard: accepts List of any type
public static void printList(List<?> list) {
for (Object item : list) [Link](item + " ");
[Link]();
}
printList([Link](1, 2, 3)); // Works with Integer
printList([Link]("a", "b", "c")); // Works with String

// Upper-bounded wildcard: ? extends Type


// Use when you ONLY READ from the collection (producer)
public static double totalArea(List<? extends Shape> shapes) {
double total = 0;
for (Shape s : shapes) total += [Link]();
return total;
}
// Can pass List<Circle>, List<Rectangle>, List<Shape>

// Lower-bounded wildcard: ? super Type


// Use when you ONLY WRITE to the collection (consumer)
public static void addNumbers(List<? super Integer> list) {
[Link](1); [Link](2); [Link](3);
}
// Can pass List<Integer>, List<Number>, List<Object>

// PECS Principle: Producer Extends, Consumer Super


// If you produce (read) data: use extends
// If you consume (write) data: use super
// If both: use explicit type parameter <T>

Interview Questions
19. What are generics? Why were they introduced in Java 5?
20. What is type erasure in Java?
21. What is the difference between List<Object> and List<?>?
22. What is the PECS principle?
23. Can we create generic arrays? Why not?
24. What is the difference between bounded and unbounded wildcards?
25. Can a generic class extend another class?

Page 12
JAVA MASTER HANDBOOK | Section 3: Advanced Java

26. What are raw types and why should we avoid them?

Page 13
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 4: Annotations

4.1 What are Annotations?


Annotations are metadata that provide information about code to the compiler, JVM, or frameworks —
without changing the program logic. They start with @ and can be applied to classes, methods, fields,
parameters, and packages.

4.2 Built-in Annotations


Annotation Purpose & Usage
@Override Tells compiler this method overrides a superclass method. Compile
error if it doesn't.
@Deprecated Marks a method/class as obsolete. Compiler warns when used.
@SuppressWarnings Suppresses specific compiler warnings. E.g.,
@SuppressWarnings("unchecked")
@FunctionalInterface Marks an interface as having exactly one abstract method. Enables
lambda use.
@SafeVarargs Suppresses unchecked warnings on varargs with generic types.
@Retention Meta-annotation: when the annotation is retained (SOURCE,
CLASS, RUNTIME)
@Target Meta-annotation: where the annotation can be applied
@Inherited Meta-annotation: annotation is inherited by subclasses
@Documented Meta-annotation: include in Javadoc
@Repeatable Meta-annotation: allows annotation to be applied multiple times

4.3 Custom Annotations


import [Link].*;

// Define a custom annotation


@Retention([Link]) // Available at runtime via reflection
@Target({[Link], [Link]}) // Can be on methods and classes
@Documented
public @interface AuditLog {
String action(); // Required element
String description() default ""; // Optional element with default
boolean logResult() default true;
}

// Another custom annotation — for field validation


@Retention([Link])
@Target([Link])
public @interface NotEmpty {
String message() default "Field cannot be empty";

Page 14
JAVA MASTER HANDBOOK | Section 3: Advanced Java

// Usage:
@AuditLog(action = "USER_LOGIN", description = "User authentication")
public class AuthService {

@NotEmpty(message = "Username is required")


private String username;

@AuditLog(action = "AUTHENTICATE", logResult = false)


public boolean authenticate(String user, String pwd) {
return "admin".equals(user) && "pass".equals(pwd);
}
}

// Reading annotations at runtime via Reflection:


Method m = [Link]("authenticate", [Link],
[Link]);
AuditLog log = [Link]([Link]);
if (log != null) {
[Link]("Action: " + [Link]());
[Link]("Log result: " + [Link]());
}

Interview Questions
27. What is an annotation in Java?
28. What are meta-annotations? Name them all.
29. What is the difference between @Retention SOURCE, CLASS, and RUNTIME?
30. How do you read annotations at runtime?
31. What is a marker annotation? Give examples.
32. How are annotations used in Spring Boot?

Page 15
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 5: Lambda Expressions (Java 8)

5.1 What is a Lambda Expression?


A lambda expression is a concise way to represent an anonymous function — a block of code that can
be passed around as a value. Lambdas are the primary way to implement functional interfaces in Java
8+.
Syntax: (parameters) -> expression OR (parameters) -> { statements; }

// BEFORE Java 8 — Anonymous inner class


Runnable r1 = new Runnable() {
@Override
public void run() {
[Link]("Running...");
}
};

// AFTER Java 8 — Lambda expression (much cleaner)


Runnable r2 = () -> [Link]("Running...");

// Lambda syntax variations:


// No parameters
Runnable noParam = () -> [Link]("Hello");

// One parameter (parentheses optional)


Consumer<String> oneParam = s -> [Link]([Link]());

// Multiple parameters
Comparator<Integer> twoParams = (a, b) -> a - b;

// Block body (multiple statements)


Comparator<String> block = (s1, s2) -> {
int result = [Link]() - [Link]();
if (result == 0) result = [Link](s2);
return result;
};

// With explicit types (usually inferred)


BinaryOperator<Integer> add = (Integer a, Integer b) -> a + b;

5.2 Built-in Functional Interfaces ([Link])


Interface Signature & Use Case
Predicate<T> boolean test(T t) — filter/condition checking. E.g., s -> [Link]() > 5
Function<T,R> R apply(T t) — transform one type to another. E.g., s -> [Link]()
Consumer<T> void accept(T t) — consume value, no return. E.g.,
[Link]::println
Supplier<T> T get() — produce value, no input. E.g., () -> new ArrayList<>()
BiFunction<T,U,R> R apply(T t, U u) — function with 2 inputs

Page 16
JAVA MASTER HANDBOOK | Section 3: Advanced Java

BiPredicate<T,U> boolean test(T t, U u) — predicate with 2 inputs


UnaryOperator<T> T apply(T t) — Function where input and output are same type
BinaryOperator<T> T apply(T t1, T t2) — BiFunction where all types are same

import [Link].*;

// Predicate — boolean condition


Predicate<String> isLong = s -> [Link]() > 5;
Predicate<String> startsA = s -> [Link]("A");
Predicate<String> combined = [Link](startsA); // Compose predicates
Predicate<String> either = [Link](startsA);
Predicate<String> notLong = [Link]();

[Link]([Link]("Algorithm")); // true (long AND starts with A)


[Link]([Link]("Alpha")); // false (not long enough)

// Function — transformation
Function<String, Integer> length = String::length;
Function<Integer, String> toStr = Object::toString;
Function<String, String> composed = [Link](toStr); // chain functions

[Link]([Link]("Hello")); // "5"

// Supplier — factory / lazy initialization


Supplier<List<String>> listFactory = ArrayList::new;
List<String> list1 = [Link]();
List<String> list2 = [Link](); // New instance each time

// Consumer — side effects


Consumer<String> print = [Link]::println;
Consumer<String> upper = s -> [Link]([Link]());
Consumer<String> both = [Link](upper);
[Link]("hello"); // prints: hello \n HELLO

// BinaryOperator — combining two values of same type


BinaryOperator<Integer> add = Integer::sum;
BinaryOperator<String> concat = String::concat;
[Link]([Link](3, 4)); // 7
[Link]([Link]("Hi", "!")); // Hi!

5.3 Method References


// Method references are shorthand for lambdas that only call one method
// Syntax: ClassName::methodName or instance::methodName

// Type 1: Static method reference — ClassName::staticMethod


Function<String, Integer> parse1 = s -> [Link](s); // lambda
Function<String, Integer> parse2 = Integer::parseInt; // method ref

// Type 2: Instance method of a particular object — instance::method


String prefix = "Hello";
Predicate<String> starts1 = s -> [Link](s);
// (Less common — method on a captured instance)

// Type 3: Instance method of arbitrary object — ClassName::instanceMethod


Function<String, String> upper1 = s -> [Link](); // lambda

Page 17
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Function<String, String> upper2 = String::toUpperCase; // method ref

Predicate<String> isEmpty1 = s -> [Link](); // lambda


Predicate<String> isEmpty2 = String::isEmpty; // method ref

// Type 4: Constructor reference — ClassName::new


Supplier<ArrayList<String>> factory1 = () -> new ArrayList<>(); // lambda
Supplier<ArrayList<String>> factory2 = ArrayList::new; // constructor
ref

Function<Integer, int[]> arrayFactory = int[]::new;


int[] arr = [Link](5); // new int[5]

// Common usage with Streams:


List<String> names = [Link]("Alice", "Bob", "Charlie");
[Link]()
.map(String::toUpperCase) // method ref
.forEach([Link]::println); // method ref

Interview Questions
33. What is a lambda expression? What is its syntax?
34. What is a functional interface? Can it have default methods?
35. What are the four types of method references?
36. What is the difference between Predicate, Function, Consumer, and Supplier?
37. Can lambda expressions throw checked exceptions?
38. What is effectively final in the context of lambdas?
39. What is the difference between lambda and anonymous inner class?
40. How does [Link](), or(), negate() work?

Page 18
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 6: Streams API (Java 8)

6.1 What is a Stream?


A Stream is a sequence of elements that supports sequential and parallel aggregate operations.
Streams don't store data — they process data from a source (collection, array, I/O channel) using a
pipeline of operations.
Key points: Streams are lazy (intermediate operations run only when a terminal operation is invoked),
stateless (operations don't modify the source), and consumable (a stream can only be traversed once).

Stream Pipeline
Source → [Intermediate Operations (lazy)] → Terminal Operation (triggers execution) Source:
collection, array, [Link](), [Link](), [Link]() Intermediate: filter, map, sorted,
distinct, limit, skip, peek, flatMap Terminal: collect, forEach, count, findFirst, anyMatch, reduce,
toList

6.2 Creating Streams


import [Link].*;

// From Collection
List<String> list = [Link]("a", "b", "c");
Stream<String> s1 = [Link]();
Stream<String> s2 = [Link](); // Parallel processing

// From array
Stream<String> s3 = [Link](new String[]{"x", "y"});
IntStream s4 = [Link](new int[]{1, 2, 3});

// [Link]()
Stream<Integer> s5 = [Link](1, 2, 3, 4, 5);

// Infinite streams
Stream<Integer> nats = [Link](0, n -> n + 1); // 0,1,2,3...
Stream<Integer> evens = [Link](0, n -> n < 100, n -> n + 2); // Java 9
Stream<Double> randoms = [Link](Math::random); // endless randoms

// Primitive streams (avoid boxing overhead)


IntStream ints = [Link](1, 6); // 1,2,3,4,5
IntStream closed = [Link](1, 5); // 1,2,3,4,5
LongStream longs = [Link](100L, 200L);
DoubleStream doubles = [Link](1.1, 2.2);

// From String
IntStream chars = "Hello".chars(); // stream of char values

// From file
Stream<String> lines = [Link]([Link]("[Link]")); // lazy!

Page 19
JAVA MASTER HANDBOOK | Section 3: Advanced Java

6.3 Intermediate Operations (Lazy)


List<String> names = [Link]("Alice", "Bob", "Charlie", "Anna", "Brian", "Clara");

// filter — keep elements matching predicate


[Link]()
.filter(n -> [Link]("A")) // [Alice, Anna]
.forEach([Link]::println);

// map — transform each element


[Link]()
.map(String::toUpperCase) // [ALICE, BOB, ...]
.map(n -> n + "!") // [ALICE!, BOB!, ...]
.forEach([Link]::println);

// mapToInt, mapToLong, mapToDouble — boxing-free transformation


int totalLen = [Link]()
.mapToInt(String::length) // IntStream
.sum();

// flatMap — flatten nested structures


List<List<Integer>> nested = [Link]([Link](1,2), [Link](3,4), [Link](5));
List<Integer> flat = [Link]()
.flatMap(Collection::stream) // Stream of all elements: 1,2,3,4,5
.collect([Link]());

// Splitting sentences into words:


List<String> sentences = [Link]("Hello World", "Java Streams");
List<String> words = [Link]()
.flatMap(s -> [Link]([Link](" ")))
.collect([Link]()); // [Hello, World, Java, Streams]

// distinct — remove duplicates


[Link](1,2,2,3,3,3,4).distinct().forEach([Link]::print); // 1234

// sorted — natural order or custom comparator


[Link]().sorted().forEach([Link]::println); // alphabetical
[Link]().sorted([Link](String::length))
.forEach([Link]::println); // by length

// limit & skip — slicing


[Link](1, n->n+1).limit(5).forEach([Link]::print); // 12345
[Link](1, n->n+1).skip(3).limit(5).forEach([Link]::print); // 45678

// peek — for debugging (don't use in production logic)


[Link]()
.peek(n -> [Link]("Before: " + n))
.filter(n -> [Link]() > 4)
.peek(n -> [Link]("After: " + n))
.count();

6.4 Terminal Operations


List<Integer> nums = [Link](3, 1, 4, 1, 5, 9, 2, 6, 5, 3);

// collect — gather results into a collection


List<Integer> asList = [Link]().collect([Link]());
Set<Integer> asSet = [Link]().collect([Link]());
List<Integer> sorted = [Link]().sorted().collect([Link]());

Page 20
JAVA MASTER HANDBOOK | Section 3: Advanced Java

// [Link] — concatenate strings


List<String> words = [Link]("Java", "Streams", "API");
String joined = [Link]().collect([Link](", ", "[", "]"));
// [Java, Streams, API]

// [Link] — group elements


Map<Integer, List<String>> byLength = [Link]()
.collect([Link](String::length));
// {4=[Java], 7=[Streams], 3=[API]}

// [Link], summingInt, averagingInt


Map<Integer, Long> countByLength = [Link]()
.collect([Link](String::length, [Link]()));

// forEach — consume each element


[Link]().distinct().forEach(n -> [Link](n + " "));

// count
long distinct = [Link]().distinct().count(); // 7

// findFirst / findAny
Optional<Integer> first = [Link]().filter(n -> n > 5).findFirst(); // 9
[Link]([Link]::println);

// anyMatch / allMatch / noneMatch


boolean anyGt5 = [Link]().anyMatch(n -> n > 5); // true
boolean allPos = [Link]().allMatch(n -> n > 0); // true
boolean noneNeg = [Link]().noneMatch(n -> n < 0); // true

// min / max
Optional<Integer> max = [Link]().max(Integer::compareTo); // 9
Optional<Integer> min = [Link]().min(Integer::compareTo); // 1

// reduce — fold elements into one value


int sum = [Link]().reduce(0, Integer::sum); // 39
int product = [Link]().reduce(1, (a,b) -> a * b);
Optional<Integer> maxR = [Link]().reduce(Integer::max); // 9

// toList() — Java 16+ shorthand


List<Integer> result = [Link]().distinct().sorted().toList();

// Statistics with IntStream


IntSummaryStatistics stats = [Link]()
.mapToInt(Integer::intValue)
.summaryStatistics();
[Link]("Count: " + [Link]());
[Link]("Sum: " + [Link]());
[Link]("Avg: " + [Link]());
[Link]("Min: " + [Link]());
[Link]("Max: " + [Link]());

6.5 Real-World Stream Examples


// ── Example 1: Employee analytics ──
record Employee(String name, String dept, double salary) {}

List<Employee> employees = [Link](


new Employee("Alice", "Engineering", 90000),

Page 21
JAVA MASTER HANDBOOK | Section 3: Advanced Java

new Employee("Bob", "Marketing", 60000),


new Employee("Charlie", "Engineering", 85000),
new Employee("Diana", "HR", 55000),
new Employee("Eve", "Engineering", 95000)
);

// Top 3 earners in Engineering


[Link]()
.filter(e -> "Engineering".equals([Link]()))
.sorted([Link](Employee::salary).reversed())
.limit(3)
.map(e -> [Link]() + ": Rs" + [Link]())
.forEach([Link]::println);

// Average salary per department


Map<String, Double> avgByDept = [Link]()
.collect([Link](
Employee::dept,
[Link](Employee::salary)
));
[Link]((dept, avg) ->
[Link]("%s: %.2f%n", dept, avg));

// Total salary bill


double total = [Link]()
.mapToDouble(Employee::salary)
.sum();
[Link]("Total payroll: Rs" + total);

// ── Example 2: Word frequency count ──


String text = "the quick brown fox jumps over the lazy dog the fox";
Map<String, Long> freq = [Link]([Link](" "))
.collect([Link](
word -> word,
[Link]()
));
[Link]().stream()
.sorted([Link].<String,Long>comparingByValue().reversed())
.limit(5)
.forEach(e -> [Link]([Link]() + ": " + [Link]()));

Interview Questions
41. What is a Stream? How is it different from a Collection?
42. What is the difference between intermediate and terminal operations?
43. What is lazy evaluation in streams?
44. Explain map vs flatMap with an example.
45. What is the difference between findFirst() and findAny()?
46. What is [Link]()? Give a real example.
47. Can a stream be reused after a terminal operation?
48. What is a parallel stream? When should you use it?
49. What is the difference between reduce() and collect()?
50. What is [Link]() vs [Link]()?

Page 22
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 7: Optional (Java 8)

7.1 What is Optional?


Optional<T> is a container class that may or may not contain a non-null value. It was introduced to
replace null checks and prevent NullPointerException. It makes the presence/absence of a value
explicit in the API.

import [Link];

// Creating Optionals
Optional<String> empty = [Link](); // Empty container
Optional<String> present = [Link]("Hello"); // Must be non-null
Optional<String> nullable = [Link](null); // Safe — null → empty
Optional<String> nullable2 = [Link]("Hi"); // non-null → present

// Checking and getting value


[Link](); // true
[Link](); // false
[Link](); // false (Java 11+)
[Link](); // "Hello" — throws NoSuchElementException if empty!

// Safe access patterns


[Link]("default"); // Returns value or default
[Link]("default"); // "default"
[Link](() -> "computed"); // Lazy default via Supplier
[Link](() -> new RuntimeException("Not found")); // Throw if empty

// Conditional actions
[Link]([Link]::println); // Prints if present, nothing if empty
[Link]( // Java 9+
v -> [Link]("Found: " + v),
() -> [Link]("Not found")
);

// Transforming Optional
Optional<Integer> length = [Link](String::length); // Optional<Integer>[5]
Optional<String> upper = [Link](String::toUpperCase); // Optional[HELLO]

// filter
Optional<String> filtered = [Link](s -> [Link]() > 3); // present
Optional<String> empty2 = [Link](s -> [Link]() > 10); // empty

// flatMap — when the mapping function returns Optional


Optional<String> name = [Link]("Alice");
Optional<String> email = [Link](n -> findEmailByName(n));

// stream() — convert Optional to Stream (Java 9+)


Optional<String> opt = [Link]("hello");
long count = [Link]().filter(s->[Link]()>3).count(); // 1

7.2 Real-World Optional Usage


// BAD — old null-checking style

Page 23
JAVA MASTER HANDBOOK | Section 3: Advanced Java

User user = [Link](id);


if (user != null) {
Address addr = [Link]();
if (addr != null) {
String city = [Link]();
if (city != null) {
[Link]([Link]());
}
}
}

// GOOD — Optional chaining


[Link](id) // Returns Optional<User>
.map(User::getAddress) // Optional<Address>
.map(Address::getCity) // Optional<String>
.map(String::toUpperCase) // Optional<String>
.ifPresent([Link]::println); // Only prints if all present

// Repository returning Optional


public Optional<Employee> findById(int id) {
return [Link]()
.filter(e -> [Link]() == id)
.findFirst();
}

// Service using it
Employee emp = [Link](42)
.orElseThrow(() -> new EmployeeNotFoundException("Employee 42 not found"));

Optional Best Practices


DO: Use Optional as a return type for methods that might not find a value. DO: Use orElse(),
orElseGet(), orElseThrow() instead of get(). DON'T: Use Optional as a field type, constructor
parameter, or method parameter. DON'T: Use [Link]() without isPresent() check — same
as null dereference. DON'T: Use Optional just to avoid null — only where absence is part of the
API contract.

Interview Questions
51. What is Optional? Why was it introduced?
52. What is the difference between [Link]() and [Link]()?
53. What does orElse() vs orElseGet() do? Which is lazy?
54. When should you NOT use Optional?
55. How do you chain multiple Optional operations?
56. What is the difference between map() and flatMap() on Optional?

Page 24
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 8: Date & Time API (Java 8)

8.1 Why a New Date API?


Before Java 8, [Link] and [Link] were the date/time APIs. They were mutable, not
thread-safe, had poor API design, and confusing month numbering (0-based). Java 8 introduced
[Link] package (inspired by Joda-Time) which is immutable, thread-safe, and intuitive.

Class Purpose
LocalDate Date without time or timezone. E.g., 2024-01-15
LocalTime Time without date or timezone. E.g., 14:30:00
LocalDateTime Date + Time without timezone. E.g., 2024-01-15T14:30:00
ZonedDateTime Date + Time + Timezone. E.g.,
2024-01-15T14:30:00+05:30[Asia/Kolkata]
Instant Timestamp in UTC (nanosecond precision). Machine-readable
moment in time.
Duration Time-based amount (hours, minutes, seconds). Between two times.
Period Date-based amount (years, months, days). Between two dates.
DateTimeFormatter Formatting and parsing date/time to/from String.
ZoneId Timezone identifier. E.g., [Link]("Asia/Kolkata")

8.2 LocalDate, LocalTime, LocalDateTime


import [Link].*;
import [Link].*;

// ── LocalDate ──────────────────────────────────────────────────
LocalDate today = [Link](); // 2024-01-15
LocalDate fixed = [Link](2024, 1, 15); // Specific date
LocalDate fromStr = [Link]("2024-01-15"); // From ISO string

// Date arithmetic (returns new instance — immutable)


LocalDate tomorrow = [Link](1);
LocalDate nextMonth = [Link](1);
LocalDate lastYear = [Link](1);
LocalDate withDay = [Link](1); // First of this month

// Date fields
[Link](); // 2024
[Link](); // JANUARY (enum)
[Link](); // 1 (1-based!)
[Link](); // 15
[Link](); // MONDAY (enum)
[Link](); // 15
[Link](); // false
[Link](); // 31

Page 25
JAVA MASTER HANDBOOK | Section 3: Advanced Java

// Comparison
LocalDate d1 = [Link](2024, 1, 1);
LocalDate d2 = [Link](2024, 6, 15);
[Link](d2); // true
[Link](d1); // true
[Link](d2); // false

// ── LocalTime ──────────────────────────────────────────────────
LocalTime now = [Link](); // 14:30:00.123
LocalTime lunch = [Link](12, 30, 0); // 12:30:00
LocalTime parsed = [Link]("09:15:30");
[Link](); // 12
[Link](); // 30

// ── LocalDateTime ──────────────────────────────────────────────
LocalDateTime ldt = [Link](2024, 1, 15, 14, 30, 0);
LocalDateTime ldt2 = [Link]();
LocalDate date = [Link]();
LocalTime time = [Link]();

8.3 Formatting & Parsing


import [Link];

LocalDateTime ldt = [Link](2024, 1, 15, 14, 30, 0);

// Predefined formatters
[Link](DateTimeFormatter.ISO_LOCAL_DATE_TIME); // 2024-01-15T14:30:00
[Link](DateTimeFormatter.ISO_LOCAL_DATE); // 2024-01-15

// Custom patterns
DateTimeFormatter f1 = [Link]("dd/MM/yyyy");
DateTimeFormatter f2 = [Link]("dd-MMM-yyyy HH:mm");
DateTimeFormatter f3 = [Link]("EEEE, d MMMM yyyy");

[Link]([Link](f1)); // 15/01/2024
[Link]([Link](f2)); // 15-Jan-2024 14:30
[Link]([Link](f3)); // Monday, 15 January 2024

// Parsing
LocalDate parsed = [Link]("15/01/2024", f1);
LocalDateTime parsedDT = [Link]("15-Jan-2024 14:30", f2);

8.4 Period, Duration, Instant


// Period — date-based difference (years, months, days)
LocalDate dob = [Link](1995, 5, 15);
LocalDate now = [Link]();
Period age = [Link](dob, now);
[Link]("Age: %d years, %d months, %d days%n",
[Link](), [Link](), [Link]());

Period oneYearSixMonths = [Link](1, 6, 0);


LocalDate future = [Link](oneYearSixMonths);

// Duration — time-based difference (hours, minutes, seconds, nanos)


LocalTime start = [Link](9, 0, 0);

Page 26
JAVA MASTER HANDBOOK | Section 3: Advanced Java

LocalTime end = [Link](17, 30, 0);


Duration workDay = [Link](start, end);
[Link]("Hours: " + [Link]()); // 8
[Link]("Minutes: " + [Link]()); // 510

Duration fiveMins = [Link](5);

// Instant — machine timestamp (UTC nanoseconds)


Instant now2 = [Link]();
Instant epoch = [Link]; // 1970-01-01T00:00:00Z
long ms = [Link](); // milliseconds since epoch

// Timing operations with Instant


Instant t1 = [Link]();
// ... operation ...
Instant t2 = [Link]();
Duration elapsed = [Link](t1, t2);
[Link]("Elapsed: " + [Link]() + "ms");

// ZonedDateTime
ZoneId kolkata = [Link]("Asia/Kolkata");
ZoneId london = [Link]("Europe/London");
ZonedDateTime zdt1 = [Link](kolkata);
ZonedDateTime zdt2 = [Link](london); // Convert timezone

Interview Questions
57. What are the problems with [Link] and Calendar?
58. What is the difference between LocalDate, LocalTime, and LocalDateTime?
59. What is the difference between Period and Duration?
60. What is Instant? How is it different from LocalDateTime?
61. How do you convert between timezones in Java 8?
62. Is [Link] immutable? Why is that important?
63. How do you parse a date string in Java 8?

Page 27
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 9: Java Version Features (8 → 21)

9.1 Java 8 (LTS — March 2014)


Java 8 was a landmark release. Key additions:
Feature Description
Lambda Expressions (params) -> expression. Enables functional programming style.
Streams API [Link] — bulk operations on collections.
Optional<T> Container for potentially null values. Avoids NPE.
Default & Static methods in Interface can have method bodies via default keyword.
interfaces
Date & Time API ([Link]) Immutable, thread-safe replacement for Date/Calendar.
Functional Interfaces @FunctionalInterface, [Link] package.
Method References ClassName::method shorthand for lambdas.
Nashorn JS Engine JavaScript engine embedded in JVM (removed in Java 15).
Base64 encoding/decoding [Link].Base64 — built-in encoding utility.
CompletableFuture Async programming with composable futures.
Metaspace PermGen replaced with native Metaspace for class metadata.

9.2 Java 9 (September 2017)


Feature Description
Module System (Project Jigsaw) [Link] — encapsulate packages into named modules.
JShell REPL Interactive Java shell for quick expression testing.
Private methods in interfaces Interface can have private helper methods.
Stream improvements takeWhile(), dropWhile(), iterate() with predicate, ofNullable()
Optional improvements ifPresentOrElse(), or(), stream()
Collection factory methods [Link](), [Link](), [Link]() — immutable collections.
HTTP/2 Client (incubator) Modern HTTP client (graduated to standard in Java 11).
Process API improvements ProcessHandle for OS process management.

// Java 9 — Collection factory methods (immutable)


List<String> names = [Link]("Alice", "Bob", "Charlie");
Set<Integer> ids = [Link](1, 2, 3, 4);
Map<String, Integer> scores = [Link]("Alice", 95, "Bob", 87);
Map<String, Integer> scores2 = [Link]( // For > 10 entries
[Link]("Alice", 95),
[Link]("Bob", 87)

Page 28
JAVA MASTER HANDBOOK | Section 3: Advanced Java

);
// [Link]("Dave"); // UnsupportedOperationException — immutable!

// Java 9 — [Link] / dropWhile


[Link](1,2,3,4,5,6,7).takeWhile(n -> n < 4).forEach([Link]::print); // 123
[Link](1,2,3,4,5,6,7).dropWhile(n -> n < 4).forEach([Link]::print); // 4567

// Java 9 — [Link] with predicate


[Link](1, n -> n <= 10, n -> n + 1).forEach([Link]::print); //
12345678910

9.3 Java 10 & 11 (LTS — September 2018)


Feature Version
var — local variable type Java 10: var name = "Alice"; // inferred as String
inference
[Link]() Java 11: Returns true for empty or whitespace-only strings
[Link]() Java 11: Unicode-aware trim (vs trim() which is ASCII-only)
[Link]() Java 11: "ab".repeat(3) → "ababab"
[Link]() Java 11: Returns Stream<String> of lines
[Link]() / writeString() Java 11: Convenient file I/O methods
HTTP Client (standard) Java 11: [Link] — modern HTTP/2 client
Running single-file programs Java 11: java [Link] (no javac needed)
[Link]() Java 10: Immutable copy of collection
[Link]() Java 10: Immutable list from stream

// Java 10 — var (local variable type inference)


var name = "Alice"; // String (inferred)
var list = new ArrayList<String>(); // ArrayList<String>
var map = new HashMap<String, Integer>(); // HashMap<String, Integer>

// var rules:
// ✅ Local variables with initializer
// ✅ For-loop variables: for (var item : list)
// ❌ Method parameters, return types, fields — NOT allowed
// ❌ var x; (no initializer — type cannot be inferred)
// ❌ var x = null; (null has no type)

// Java 11 — String methods


" hello ".strip(); // "hello"
" ".isBlank(); // true
"a\nb\nc".lines() // Stream: ["a", "b", "c"]
.collect([Link]());
"ha".repeat(3); // "hahaha"

// Java 11 — HTTP Client


HttpClient client = [Link]();
HttpRequest request = [Link]()
.uri([Link]("[Link]
.GET()

Page 29
JAVA MASTER HANDBOOK | Section 3: Advanced Java

.build();
HttpResponse<String> response = [Link](request,
[Link]());
[Link]([Link]()); // 200
[Link]([Link]());

9.4 Java 14–16 Features


Feature Description
Records (Java 16 GA) Compact immutable data classes. auto-generates constructor,
getters, equals, hashCode, toString.
Pattern Matching instanceof if (obj instanceof String s) — no explicit cast needed.
(Java 16 GA)
Sealed Classes (Java 17 GA) Restrict which classes can extend/implement a class/interface.
Switch Expressions (Java 14 switch as expression, arrow syntax, yield.
GA)
Text Blocks (Java 15 GA) Multi-line string literals with triple quotes.
Helpful NullPointerExceptions JVM shows which variable was null: Cannot invoke [Link]()
(Java 14) because name is null

// Records (Java 16) — immutable data carrier


record Point(double x, double y) {
// Compact canonical constructor for validation
Point {
if (x < 0 || y < 0) throw new IllegalArgumentException("Coords must be >=
0");
}

// Can add custom methods


double distanceTo(Point other) {
return [Link]([Link](x - other.x, 2) + [Link](y - other.y, 2));
}
}

Point p = new Point(3.0, 4.0);


[Link](p.x()); // 3.0 (auto-generated accessor)
[Link](p); // Point[x=3.0, y=4.0] (auto toString)
[Link]([Link](new Point(3.0, 4.0))); // true (auto equals)

// Sealed Classes (Java 17)


public sealed class Shape permits Circle, Rectangle, Triangle { }
public final class Circle extends Shape { double radius; }
public final class Rectangle extends Shape { double w, h; }
public non-sealed class Triangle extends Shape { } // Can be extended further

// Sealed + Records + Pattern matching (perfect combo):


double area = switch (shape) {
case Circle c -> [Link] * [Link] * [Link];
case Rectangle r -> r.w * r.h;
case Triangle t -> 0.5 * [Link] * [Link];
};

// Text Blocks (Java 15)

Page 30
JAVA MASTER HANDBOOK | Section 3: Advanced Java

String json = """


{
"name": "Alice",
"age": 30,
"email": "alice@[Link]"
}
""";

String html = """


<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>
""";

9.5 Java 17 (LTS) & Java 21 (LTS)


Feature Description
Virtual Threads (Java 21 GA) Lightweight threads managed by JVM, not OS. Millions can run
concurrently.
Sequenced Collections (Java SequencedCollection, SequencedSet, SequencedMap — ordered
21) collection interfaces with getFirst(), getLast(), reversed().
Record Patterns (Java 21 GA) Destructure records in pattern matching: case Point(double x,
double y) p
Pattern Matching for switch Full pattern matching in switch expressions/statements.
(Java 21 GA)
String Templates (Java 21 STR."Hello \{name}!" — interpolation syntax.
Preview)
Unnamed Classes (Java 21 void main() — no class wrapper needed for simple programs.
Preview)

// Virtual Threads (Java 21) — massive concurrency


// Traditional thread: 1 Java thread = 1 OS thread (~1MB stack)
// Virtual thread: lightweight, JVM-managed, ~few hundred bytes

// Create virtual threads:


Thread vt = [Link]().start(() -> {
[Link]("Virtual thread running: " + [Link]());
});

// Virtual thread executor:


try (ExecutorService exec = [Link]()) {
[Link](0, 1_000_000).forEach(i ->
[Link](() -> {
[Link]([Link](100)); // blocks virtual, not OS thread
return i * 2;
})
);
} // Runs 1 million tasks efficiently!

// Sequenced Collections (Java 21)


SequencedCollection<String> list = new ArrayList<>([Link]("a","b","c"));

Page 31
JAVA MASTER HANDBOOK | Section 3: Advanced Java

[Link](); // "a"
[Link](); // "c"
[Link]("z"); // [z, a, b, c]
[Link](); // reversed view: [c, b, a, z]

// Record Pattern Matching (Java 21)


record Employee(String name, double salary) {}
Object obj = new Employee("Alice", 90000.0);

if (obj instanceof Employee(String name, double salary)) {


[Link](name + " earns " + salary);
}

// Switch with patterns (Java 21)


String describe(Object o) {
return switch (o) {
case Integer i when i < 0 -> "Negative int: " + i;
case Integer i -> "Positive int: " + i;
case String s when [Link]() -> "Blank string";
case String s -> "String: " + s;
case null -> "null value";
default -> "Other: " + o;
};
}

Interview Questions
64. What are the major features added in Java 8?
65. What is the difference between var (Java 10) and dynamic typing?
66. What is a Record in Java 16? When should you use it?
67. What is a sealed class? What keywords does it use?
68. What are virtual threads? How are they different from platform threads?
69. What are text blocks? How do you escape triple quotes inside?
70. What is pattern matching for switch in Java 21?
71. What is a Sequenced Collection?
72. What are the LTS versions of Java and why do they matter?

Page 32
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 10: Inner Classes

10.1 Types of Inner Classes


Type Description
Non-static inner class Defined inside a class, without static. Has access to all outer class
members including private.
Static nested class Defined with static keyword. Cannot access outer class instance
members directly.
Local class Defined inside a method. Visible only within that method.
Anonymous class No name, defined and instantiated at the same time. Used for one-
time implementations.

public class Outer {


private int value = 10;
private static int staticVal = 20;

// Non-static inner class


class Inner {
void display() {
[Link]("Outer value: " + value); // access outer
private
[Link]("Static val: " + staticVal); // access outer
static
}
}

// Static nested class


static class StaticNested {
void display() {
// [Link](value); // ERROR — no outer instance
[Link]("Static val: " + staticVal); // static OK
}
}

void methodWithLocalClass() {
final String msg = "Hello from local";

// Local class
class LocalGreeter {
void greet() { [Link](msg); } // accesses effectively
final
}
new LocalGreeter().greet();
}
}

// Creating instances:
Outer outer = new Outer();
[Link] inner = [Link] Inner(); // Non-static: needs outer instance
[Link]();

[Link] nested = new [Link](); // Static: no outer needed


[Link]();

Page 33
JAVA MASTER HANDBOOK | Section 3: Advanced Java

// Anonymous class — for one-time interface/abstract class implementation


Runnable r = new Runnable() {
@Override
public void run() {
[Link]("Running anonymously");
}
};
[Link]();

// Modern equivalent: lambda


Runnable r2 = () -> [Link]("Running with lambda");

Interview Questions
73. What are the types of inner classes in Java?
74. What is the difference between static nested class and non-static inner class?
75. Why does an inner class have access to outer class private members?
76. What is an anonymous class? How is it different from a lambda?
77. Can an inner class be static?
78. What is the memory implication of using non-static inner classes?

Page 34
JAVA MASTER HANDBOOK | Section 3: Advanced Java

Chapter 11: Reflection API

11.1 What is Reflection?


Reflection is the ability of a Java program to inspect and modify its own structure (classes, methods,
fields, constructors) at runtime. It is used by frameworks like Spring, Hibernate, JUnit, and Jackson to
operate without knowing classes at compile time.

import [Link].*;

public class ReflectionDemo {


public static void main(String[] args) throws Exception {

// Get Class object (three ways)


Class<?> c1 = [Link]; // via .class literal
Class<?> c2 = "hello".getClass(); // via instance
Class<?> c3 = [Link]("[Link]"); // via name

[Link]([Link]()); // [Link]
[Link]([Link]()); // String
[Link]([Link]()); // [Link]

// Get fields
Field[] fields = [Link](); // All fields (incl private)
for (Field f : fields) {
[Link]([Link]() + " : " + [Link]().getName());
}

// Get methods
Method[] methods = [Link](); // All public methods (inherited too)
Method lengthMethod = [Link]("length"); // Specific method

// Invoke method via reflection


String s = "Hello, Reflection!";
int len = (int) [Link](s);
[Link]("Length via reflection: " + len); // 18

// Get constructors
Constructor<?>[] ctors = [Link]();
Constructor<String> ctor = [Link]([Link]);
String newStr = [Link]("Created via reflection");
[Link](newStr);

// Access private field (use with caution)


class Person { private String secret = "confidential"; }
Person p = new Person();
Field secretField = [Link]("secret");
[Link](true); // bypass private
[Link]([Link](p)); // confidential
[Link](p, "modified"); // modify private field!
}
}

Reflection Use Cases & Warnings


USE CASES: Dependency injection (Spring), ORM mapping (Hibernate), JSON serialization

Page 35
JAVA MASTER HANDBOOK | Section 3: Advanced Java

(Jackson), unit testing (JUnit), plugin architectures. WARNINGS: Slow (bypasses JVM
optimizations), breaks encapsulation, can cause security issues, suppresses compile-time
checks. Use only when absolutely necessary. In Java 9+, module system restricts deep
reflection by default.

Interview Questions
79. What is reflection in Java?
80. What are the use cases of reflection?
81. How do you access a private field using reflection?
82. What is setAccessible(true)? Is it safe to use?
83. How does Spring use reflection internally?
84. What are the performance implications of reflection?

End of Section 3: Advanced Java


Java Master Handbook | Next: Section 4 — Collection Framework

Page 36

You might also like