☕ CuesysLearn Main Website 🔥 Learning Portal
info@cuesysinfotech.com Contact
CuesysLearn
Java & Spring Bootby Cuesys Infotech Pvt Ltd
Free Training
🔥 Learning Portal 🔒 SAP Security ☁️ Cloud Computing ☕ Java & Spring Boot 🐍 Python with AI 📈 SQL with AI 🏫 Free Training
🔥 Learning Portal ☕ Java & Spring Boot
☕ JAVA & SPRING BOOT ❓ Interview Ready Beginner → Advanced

Java & Spring Boot
Complete Notes

Master Java from core fundamentals to enterprise-level development — OOP, Collections, Streams, Spring Boot, REST APIs, Microservices, JPA/Hibernate and Design Patterns. Everything to crack Java interviews at top MNCs and clear Oracle Java certifications.

📋 12 Topics Covered
❓ 100+ Interview Q&As
🏅 OCP / OCJP Ready
💻 Code Examples
✅ Java 21 Updated

📚 Welcome to Java & Spring Boot

Java is the world's most widely deployed programming language — running on 3 billion+ devices. It powers Android apps, enterprise back-end systems, banking platforms, e-commerce sites and cloud applications. Java developers are among the highest paid in India — ₹6–40 LPA depending on experience and skills.

Spring Boot is the most popular Java framework for building production-ready applications fast. Together, Java + Spring Boot is the #1 skill combination for back-end and full-stack Java roles at companies like TCS, Infosys, Wipro, Cognizant and top product companies.

Java Basics
Syntax, variables, data types, control flow, methods
🎲
OOP
Encapsulation, inheritance, polymorphism, abstraction
📚
Collections
List, Set, Map, Queue — internals, time complexity, when to use
💥
Exception Handling
Checked vs unchecked, custom exceptions, try-with-resources
Streams & Lambda
Functional programming, Stream API, method references
🍀
Spring Boot
Auto-configuration, dependency injection, starter projects
🔗
REST APIs
CRUD endpoints, validation, error handling, Postman testing
📈
JPA & Hibernate
ORM concepts, entity mapping, JPQL, relationships
⚖️
Microservices
Service decomposition, Eureka, API Gateway, circuit breaker
💫
Design Patterns
Singleton, Factory, Observer, Builder, MVC, Proxy
Interview Q&A
100+ real questions from top MNC interviews
🏅
Certifications
OCJP/OCP SE 17 complete exam prep guide

💡 How to use this page: Click any topic in the left sidebar. All notes load instantly — no page reloads. Every section has real working Java code examples. Use Prev / Next to go in order from beginner to advanced.

☕ Java Basics & Syntax

Beginner

Java Platform — JDK, JRE, JVM

ComponentFull NameContainsUsed By
JDKJava Development KitJRE + Compiler (javac) + Tools (jar, javadoc)Developers — to write and compile Java code
JREJava Runtime EnvironmentJVM + Core Libraries (java.lang, java.util, etc.)End users — to run Java applications
JVMJava Virtual MachineBytecode interpreter, JIT compiler, Garbage CollectorExecutes .class bytecode files on any OS

💡 Write Once, Run Anywhere: Java source code (.java) → compiled by javac to bytecode (.class) → JVM reads bytecode and executes it on ANY platform. This is why Java runs identically on Windows, Mac, Linux and Android.

Data Types, Variables & Control Flow

JAVA// Primitive data types int age = 25; double salary = 85000.50; boolean isActive = true; char grade = 'A'; long bigNum = 9876543210L; // String — not primitive, it's an object String name = "Hari Krishna"; String msg = "Hello, " + name; // Concatenation String info = String.format("Name: %s, Age: %d", name, age); // Control flow if (age >= 18) { System.out.println("Adult"); } else { System.out.println("Minor"); } // Enhanced switch (Java 14+) String dayType = switch (day) { case "MON", "TUE", "WED", "THU", "FRI" -> "Weekday"; case "SAT", "SUN" -> "Weekend"; default -> "Invalid"; };

Methods & Varargs

JAVA// Method with return type public static int add(int a, int b) { return a + b; } // Method overloading — same name, different params public static double add(double a, double b) { return a + b; } // Varargs — variable number of arguments public static int sum(int... numbers) { int total = 0; for (int n : numbers) total += n; return total; } sum(1, 2, 3); // 6 sum(10, 20); // 30 sum(5, 5, 5, 5); // 20

String Methods — Most Asked in Interviews

JAVAString s = " Hello World "; s.length() // 15 s.trim() // "Hello World" s.toUpperCase() // " HELLO WORLD " s.toLowerCase() // " hello world " s.contains("World") // true s.replace("World", "Java") // " Hello Java " s.split(" ") // ["", "", "Hello", "World", "", ""] s.charAt(2) // 'H' s.substring(2, 7) // "Hello" s.indexOf("World") // 8 s.isEmpty() // false s.isBlank() // false (Java 11+) // == vs .equals() — CRITICAL interview question! String a = new String("hello"); String b = new String("hello"); a == b // false — different objects in heap a.equals(b) // true — same content // String Pool — literal strings are cached String c = "hello"; String d = "hello"; c == d // true — same pool reference

🎲 Object-Oriented Programming — 4 Pillars

Beginner → Intermediate

OOP is the foundation of Java. Every interview tests OOP deeply — not just definitions, but real code examples and when to use each concept. Master these 4 pillars completely.

1. Encapsulation — Data Hiding

JAVA — ENCAPSULATIONpublic class BankAccount { private double balance; // Private — cannot be accessed directly private String accountNumber; // Controlled access via getter/setter public double getBalance() { return balance; } public void deposit(double amount) { if (amount > 0) { // Business validation before setting balance += amount; } else { throw new IllegalArgumentException("Amount must be positive"); } } } // Cannot do: account.balance = -5000 → compile error // Must do: account.deposit(-5000) → throws exception safely

2. Inheritance — Code Reuse

JAVA — INHERITANCEpublic class Employee { protected String name; protected double baseSalary; public Employee(String name, double salary) { this.name = name; this.baseSalary = salary; } public double calculatePay() { return baseSalary; } } public class Manager extends Employee { // Inherits all Employee fields/methods private double bonus; public Manager(String name, double salary, double bonus) { super(name, salary); // Call parent constructor this.bonus = bonus; } @Override public double calculatePay() { // Override — runtime polymorphism return baseSalary + bonus; } }

3. Polymorphism — Many Forms

JAVA — POLYMORPHISM// Compile-time polymorphism — Method Overloading public class Calculator { public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; } public String add(String a, String b) { return a + b; } } // Runtime polymorphism — Method Overriding (dynamic dispatch) Employee emp = new Manager("Hari", 50000, 10000); // emp is Employee type but points to Manager object emp.calculatePay(); // Calls Manager's calculatePay() — not Employee's! // JVM decides at RUNTIME which implementation to call

4. Abstraction — Abstract Classes & Interfaces

JAVA — ABSTRACTION// Abstract class — can have abstract + concrete methods public abstract class Shape { private String color; public abstract double area(); // Must be implemented by subclass public abstract double perimeter(); public void describe() { // Concrete method — shared logic System.out.println("Area: " + area()); } } // Interface — Java 8+ allows default and static methods public interface Payable { double calculatePay(); // Abstract by default default void printPayslip() { // Default method (Java 8+) System.out.println("Pay: " + calculatePay()); } } // Class can extend ONE abstract class + implement MULTIPLE interfaces public class Circle extends Shape implements Payable, Drawable { private double radius; public double area() { return Math.PI * radius * radius; } public double perimeter() { return 2 * Math.PI * radius; } public double calculatePay() { return 0; } }

Abstract Class vs Interface — Key Differences

FeatureAbstract ClassInterface
InstantiationCannot instantiate directlyCannot instantiate directly
MethodsAbstract + concrete methodsAbstract + default + static methods (Java 8+)
VariablesInstance variables (any type)public static final constants only
ConstructorHas constructorsNo constructors
InheritanceSingle inheritance (extends one)Multiple implementation (implements many)
Access ModifiersAny (private, protected, public)public and default only
When to useIS-A relationship with shared stateCAN-DO (capability contract) — Flyable, Serializable

📚 Collections Framework

Intermediate

The Java Collections Framework is one of the most heavily tested topics in every Java interview. You must know not just what each collection is — but how it works internally, its time complexity and exactly when to use it.

Collections Hierarchy Overview

InterfaceKey Impl.Ordered?Duplicates?Thread-Safe?Time: get/putBest Use
ListArrayListYes (index)YesNo (use CopyOnWriteArrayList)O(1) get, O(n) add(mid)Ordered list with duplicates — most common choice
ListLinkedListYes (index)YesNoO(n) get, O(1) add/remove endsFrequent insertion/deletion at beginning or middle
SetHashSetNoNoNo (use ConcurrentHashMap.newKeySet())O(1) avgUnique items, fast lookup, order does not matter
SetLinkedHashSetInsertionNoNoO(1) avgUnique items in insertion order
SetTreeSetSortedNoNoO(log n)Unique items always kept sorted (natural order or Comparator)
MapHashMapNoKeys: NoNo (use ConcurrentHashMap)O(1) avgKey-value pairs, fastest general purpose — most used Map
MapLinkedHashMapInsertionKeys: NoNoO(1)Key-value with predictable iteration order
MapTreeMapSorted by keyKeys: NoNoO(log n)Key-value always sorted by key

HashMap — How It Works Internally

JAVA — HASHMAP INTERNALS// HashMap uses array of buckets (default 16) + LinkedList/Tree // put("key", value) process: // 1. Call key.hashCode() → get hash integer // 2. Spread: hash ^ (hash >>> 16) // 3. Index = hash & (capacity - 1) // 4. If bucket empty → new Node. If occupied → use .equals() // 5. When bucket size > 8 → convert LinkedList to Red-Black Tree (Java 8+) // 6. When size > capacity * loadFactor(0.75) → resize (double capacity) Map<String, Integer> scores = new HashMap<>(); scores.put("Ravi", 92); scores.put("Priya", 88); scores.get("Ravi"); // 92 — O(1) average scores.getOrDefault("Unknown", 0); // 0 (safe — no NPE) scores.containsKey("Priya"); // true scores.putIfAbsent("Ravi", 100); // ignored — Ravi already exists // Iterating for (Map.Entry<String, Integer> entry : scores.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } // Java 8+ forEach with lambda scores.forEach((k, v) -> System.out.println(k + ": " + v));

💥 Exception Handling

Intermediate

Exception Hierarchy

TypeSuperclassMust Handle?ExamplesRepresents
Checked ExceptionExceptionYES — compile error if not handledIOException, SQLException, ClassNotFoundExceptionRecoverable external conditions — file not found, network failure
Unchecked ExceptionRuntimeExceptionNO — optional to handleNullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentExceptionProgramming bugs — should be fixed, not caught
ErrorErrorNO — do not catchOutOfMemoryError, StackOverflowErrorJVM-level problems — application cannot recover

try-catch-finally & Custom Exceptions

JAVA// Custom exception public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { super("Insufficient funds. Short by: ₹" + amount); this.amount = amount; } } public void withdraw(double amount) throws InsufficientFundsException { if (amount > balance) { throw new InsufficientFundsException(amount - balance); } balance -= amount; } // try-with-resources (Java 7+) — auto closes resources try (FileReader fr = new FileReader("data.txt"); BufferedReader br = new BufferedReader(fr)) { String line = br.readLine(); System.out.println(line); } catch (FileNotFoundException e) { System.err.println("File not found: " + e.getMessage()); } catch (IOException e) { System.err.println("IO Error: " + e.getMessage()); } finally { // Runs ALWAYS — file auto-closed by try-with-resources above System.out.println("Processing complete"); }

⚡ Streams & Lambda — Java 8+

Intermediate → Advanced

Java 8 (2014) was the biggest update in Java's history. Lambda expressions and the Stream API transformed Java from verbose OOP-only to supporting functional programming style. These are asked in every senior Java interview.

Lambda Expressions & Functional Interfaces

JAVA — LAMBDA// Traditional anonymous class (verbose) Runnable r1 = new Runnable() { public void run() { System.out.println("Running"); } }; // Lambda equivalent — same thing, much cleaner Runnable r2 = () -> System.out.println("Running"); // Built-in functional interfaces Function<String, Integer> strLen = s -> s.length(); // T → R Predicate<Integer> isEven = n -> n % 2 == 0; // T → boolean Consumer<String> printer = s -> System.out.println(s); Supplier<String> greeter = () -> "Hello!"; // Method reference — even cleaner than lambda Consumer<String> printer2 = System.out::println; // same as above

Stream API — Complete Operations

JAVA — STREAM APIList<String> courses = List.of("SAP Security", "Python AI", "SQL", "Java", "Cloud"); // filter + map + collect — most common pattern List<String> shortCourses = courses.stream() .filter(c -> c.length() <= 5) // keep only short names .map(String::toUpperCase) // transform each .sorted() // alphabetical order .collect(Collectors.toList()); // ["CLOUD", "JAVA", "SQL"] // Aggregate operations long count = courses.stream().count(); Optional<String> first = courses.stream().findFirst(); boolean anyMatch = courses.stream().anyMatch(c -> c.contains("SAP")); // Group by length — Collectors.groupingBy Map<Integer, List<String>> byLength = courses.stream() .collect(Collectors.groupingBy(String::length)); // flatMap — flatten nested lists List<List<Integer>> nested = List.of(List.of(1,2), List.of(3,4)); List<Integer> flat = nested.stream() .flatMap(Collection::stream) .collect(Collectors.toList()); // [1, 2, 3, 4]

🍀 Spring Boot Fundamentals

Intermediate

Spring Boot is an opinionated extension of the Spring Framework that makes it easy to create stand-alone, production-grade Spring applications. "Convention over configuration" — Spring Boot auto-configures most of what you need based on your dependencies.

Spring Core Concepts

ConceptWhat It IsExample
IoC ContainerInversion of Control — Spring creates and manages your objects (beans), not youSpring creates StudentService and injects its dependencies automatically
Dependency InjectionSpring injects objects your class needs — via Constructor, Setter or Field@Autowired StudentRepository repo — Spring injects the implementation
BeanAny object managed by the Spring IoC container@Service, @Repository, @Controller, @Component classes are all beans
@SpringBootApplicationMain annotation — enables @Configuration + @ComponentScan + @EnableAutoConfigurationPut on your main class — Spring scans and configures everything
Auto-configurationSpring detects classpath dependencies and configures beans automaticallyAdd H2 dependency → Spring auto-creates in-memory database and DataSource
application.propertiesCentral configuration file — DB URL, server port, JPA settings, loggingspring.datasource.url=jdbc:mysql://localhost:3306/mydb

Spring Boot Application Structure

JAVA — SPRING BOOT// Main class @SpringBootApplication public class CuesysApplication { public static void main(String[] args) { SpringApplication.run(CuesysApplication.class, args); } } // Entity — maps to database table @Entity @Table(name = "students") public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotBlank private String name; @Email private String email; } // Repository — data access layer @Repository public interface StudentRepository extends JpaRepository<Student, Long> { List<Student> findByName(String name); Optional<Student> findByEmail(String email); } // Service — business logic layer @Service public class StudentService { private final StudentRepository repo; public StudentService(StudentRepository repo) { // Constructor injection this.repo = repo; } public Student enroll(Student student) { return repo.save(student); } }

🔗 REST API Development with Spring Boot

Intermediate

Complete CRUD REST Controller

JAVA — REST CONTROLLER@RestController @RequestMapping("/api/students") public class StudentController { private final StudentService service; public StudentController(StudentService service) { this.service = service; } // GET /api/students — get all @GetMapping public ResponseEntity<List<Student>> getAll() { return ResponseEntity.ok(service.findAll()); } // GET /api/students/5 — get one by ID @GetMapping("/{id}") public ResponseEntity<Student> getById(@PathVariable Long id) { return service.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } // POST /api/students — create new @PostMapping public ResponseEntity<Student> create(@Valid @RequestBody Student s) { Student saved = service.save(s); URI location = URI.create("/api/students/" + saved.getId()); return ResponseEntity.created(location).body(saved); } // PUT /api/students/5 — update @PutMapping("/{id}") public ResponseEntity<Student> update(@PathVariable Long id, @Valid @RequestBody Student s) { return ResponseEntity.ok(service.update(id, s)); } // DELETE /api/students/5 @DeleteMapping("/{id}") public ResponseEntity<Void> delete(@PathVariable Long id) { service.delete(id); return ResponseEntity.noContent().build(); } } // Global exception handler @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) { return ResponseEntity.status(404).body(new ErrorResponse(ex.getMessage())); } }

HTTP Methods & Status Codes

MethodPurposeSuccess CodeHas Body?
GETRetrieve resource(s)200 OKResponse only
POSTCreate new resource201 Created (+ Location header)Request + Response
PUTReplace entire resource200 OKRequest + Response
PATCHPartial update200 OKRequest + Response
DELETEDelete resource204 No ContentNo response body

📈 JPA & Hibernate

Intermediate → Advanced

JPA (Java Persistence API) is the specification for ORM in Java. Hibernate is the most popular implementation. Together they map Java objects to database tables — eliminating most manual SQL for CRUD operations.

Entity Relationships

JAVA — JPA RELATIONSHIPS// @OneToMany — One course has many enrollments @Entity public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "course", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Enrollment> enrollments; } // @ManyToOne — Many enrollments belong to one course @Entity public class Enrollment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "course_id") private Course course; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "student_id") private Student student; private LocalDate enrollDate; private Integer score; }

JPQL Queries & N+1 Problem

JAVA — JPQL + N+1 FIX// JPQL — object-oriented query language @Query("SELECT e FROM Enrollment e WHERE e.score >= :minScore ORDER BY e.score DESC") List<Enrollment> findHighScorers(@Param("minScore") int minScore); // N+1 Problem — BAD: 1 query for courses + N queries for enrollments List<Course> courses = courseRepo.findAll(); courses.forEach(c -> c.getEnrollments().size()); // N+1 queries! // FIX — JOIN FETCH loads everything in ONE query @Query("SELECT c FROM Course c LEFT JOIN FETCH c.enrollments") List<Course> findAllWithEnrollments(); // Or use @EntityGraph @EntityGraph(attributePaths = {"enrollments"}) List<Course> findAll();

💡 EAGER vs LAZY loading: LAZY (default for @OneToMany) = load related data only when accessed — better performance. EAGER = load everything immediately — can cause performance issues with large datasets. Always use LAZY and fix N+1 with JOIN FETCH or @EntityGraph when needed.

⚖️ Microservices with Spring Boot

Advanced

Microservices is an architectural approach where a large application is broken into small, independent services — each with its own database, deployable separately. This is the dominant architecture at companies like Netflix, Amazon and Uber.

Monolith vs Microservices

AspectMonolithMicroservices
DeploymentDeploy entire app for any changeDeploy only the changed service independently
ScalingScale entire applicationScale only the bottleneck service
TechnologyOne tech stackEach service can use a different language/DB
Team SizeOne large teamSmall independent teams per service (2-pizza rule)
FailureOne bug can bring down everythingFailures are isolated to one service
ComplexitySimple to startComplex — distributed systems problems
DatabaseOne shared databaseEach service has its own dedicated database

Key Spring Cloud Components

1
Eureka (Service Registry) — Services register themselves with Eureka on startup. Other services discover them by name — no hardcoded IPs. If a service dies, Eureka removes it. Netflix open-sourced this.
2
Spring Cloud Gateway (API Gateway) — Single entry point for all clients. Routes requests to correct microservices. Handles cross-cutting concerns: authentication, rate limiting, logging, SSL termination.
3
OpenFeign (HTTP Client) — Declarative REST client — call another microservice like a local method. Auto-handles service discovery via Eureka. @FeignClient("student-service") makes remote calls look local.
4
Resilience4j (Circuit Breaker) — Prevents cascade failures. If Student Service is down and Order Service keeps calling it, it will fail too. Circuit Breaker opens after N failures — returns fallback response instead.
5
Spring Cloud Config — Centralised configuration management. All microservices read their config from a central Git repo. Change config in one place — all services update without restart.
6
Distributed Tracing (Zipkin) — Track a single request as it flows across multiple microservices. Essential for debugging — see which service is slow, where an error originated.

💫 Design Patterns

Advanced

Design patterns are proven, reusable solutions to commonly occurring software design problems. The "Gang of Four" (GoF) book documented 23 patterns in 1994. Senior Java interviews always test these — not just "what is it" but "when and why to use it."

Most Asked Patterns in Java Interviews

JAVA — SINGLETON PATTERN// Singleton — only ONE instance ever created public class DatabaseConnection { private static volatile DatabaseConnection instance; // volatile for thread safety private DatabaseConnection() {} // Private constructor — prevents external instantiation public static DatabaseConnection getInstance() { if (instance == null) { synchronized (DatabaseConnection.class) { // double-checked locking if (instance == null) { instance = new DatabaseConnection(); } } } return instance; } }
JAVA — BUILDER PATTERN// Builder — construct complex objects step by step public class CourseEnrollment { private final String studentName; private final String courseName; private final String mode; private final int duration; private CourseEnrollment(Builder b) { // Private constructor this.studentName = b.studentName; this.courseName = b.courseName; this.mode = b.mode; this.duration = b.duration; } public static class Builder { private String studentName, courseName; private String mode = "Online"; // default private int duration = 30; // default public Builder studentName(String s) { this.studentName = s; return this; } public Builder courseName(String c) { this.courseName = c; return this; } public Builder mode(String m) { this.mode = m; return this; } public Builder duration(int d) { this.duration = d; return this; } public CourseEnrollment build() { return new CourseEnrollment(this); } } } // Usage — readable, fluent CourseEnrollment e = new CourseEnrollment.Builder() .studentName("Ravi Kumar") .courseName("Java & Spring Boot") .mode("Onsite") .duration(5) .build();

SOLID Principles — Clean Code Foundation

PrincipleMeaningViolation ExampleFix
S — Single ResponsibilityEvery class should have ONE reason to changeUserService handles users, sends emails AND logs to DBSeparate: UserService, EmailService, AuditService
O — Open/ClosedOpen for extension, closed for modificationAdd if-else for each new payment typeUse Payment interface, add new PayPalPayment class
L — Liskov SubstitutionSubclass should be replaceable by its superclassSquare extends Rectangle but breaks area calculationSeparate Square and Rectangle hierarchies
I — Interface SegregationClients should not depend on methods they do not useOne fat IAnimal interface with fly(), swim(), run()Separate: IFlyable, ISwimmable, IRunnable
D — Dependency InversionDepend on abstractions, not concrete implementationsnew MySQLDatabase() hardcoded in serviceInject Database interface — switch impl without changing service

❓ Java & Spring Boot Interview Q&A

Most frequently asked questions at TCS, Infosys, Wipro, Cognizant, Accenture, Amazon, and product companies. Click to reveal model answers.

Q1. What is the difference between == and .equals() in Java? +

Model Answer:

== compares references — it checks if two variables point to the exact same object in memory. For primitive types (int, boolean etc.), == compares values. The .equals() method compares object content. Its default implementation in the Object class uses == (reference comparison), but String, Integer and most other classes override it to compare by value. Critical example: String a = new String("hello"); String b = new String("hello"); a == b is FALSE (different heap objects). a.equals(b) is TRUE (same content). However, String literals use the String Pool: String c = "hello"; String d = "hello"; c == d is TRUE (same pool reference). Rule: always use .equals() for object comparison. Use == only for primitive comparison and reference identity checks. For null-safe comparison: use Objects.equals(a, b) which handles null without NPE.

Q2. Explain HashMap internal working. What happens on hash collision? +

Model Answer:

HashMap uses an array of "buckets" (default initial capacity 16) combined with linked lists (and Red-Black Trees from Java 8+ when a bucket exceeds 8 entries). On put(key, value): (1) key.hashCode() is called. (2) Hash is further processed: hash ^ (hash >>> 16) to spread bits. (3) Bucket index = hash & (capacity-1). (4) If bucket is empty, create a new Node. (5) If occupied, .equals() checks if the key already exists — update value if yes, add new Node to chain if no — this is a collision. (6) Load Factor (default 0.75): when 75% of buckets are occupied, HashMap resizes — capacity doubles and all entries are rehashed. Java 8 improvement: when a single bucket has more than 8 nodes, the linked list converts to a Red-Black Tree, improving worst-case time from O(n) to O(log n). Always override both hashCode() and equals() together — if two objects are equal, they must have the same hashCode.

Q3. What is the difference between ArrayList and LinkedList? +

Model Answer:

ArrayList uses a dynamic array internally. It gives O(1) random access by index (array indexing), O(1) amortized add at the end, but O(n) for insertion or removal in the middle (elements must shift). Memory: compact, just an array. LinkedList uses a doubly linked list. It gives O(1) add/remove at both ends, O(n) for random access by index (must traverse from head). Memory: each node stores data + two pointers — higher overhead. When to use ArrayList: most cases — random access, mostly reading, appending at end. When to use LinkedList: frequent insertion/deletion at the beginning or middle, implementing a Queue or Deque. In practice, ArrayList outperforms LinkedList in most real scenarios due to CPU cache locality (contiguous memory). Rule of thumb: use ArrayList by default, switch to LinkedList only if profiling shows it is a bottleneck.

Q4. What is the difference between abstract class and interface? When to use which? +

Model Answer:

Abstract class: can have abstract and concrete methods, instance variables, constructors, any access modifiers. A class can only extend ONE abstract class. Use when classes share state (instance variables) and some common implementation — IS-A relationship with partial implementation. Example: Vehicle abstract class with common fuel() method but abstract drive() method. Interface: all fields are public static final (constants), all methods are implicitly public. Since Java 8: can have default and static methods. A class can implement MULTIPLE interfaces. Use for capability contracts — what an object CAN DO regardless of its class hierarchy: Serializable, Comparable, Runnable. The key question: IS-A (abstract class) vs CAN-DO (interface). If you have a Dog and a Cat, both ARE-A Animal (abstract class). Both CAN-DO Trainable, Playable (interfaces). Real design tip: prefer interfaces for type definitions — they give more flexibility and support multiple implementation.

Q5. What is dependency injection and how does Spring implement it? +

Model Answer:

Dependency Injection (DI) is a design pattern where objects receive their dependencies from outside rather than creating them internally. Benefits: decoupling, testability (can inject mock objects for testing), flexibility (change implementation without touching the class). Spring implements DI through its IoC container. Three types: (1) Constructor Injection — dependencies passed via constructor. Best practice — makes dependencies explicit and supports immutability. @Autowired on constructor (optional in Spring 4.3+ if single constructor). (2) Setter Injection — dependencies set via setter methods. Use for optional dependencies. (3) Field Injection — @Autowired directly on field. Convenient but not recommended — hides dependencies, makes testing harder. Spring prefers Constructor Injection. How Spring creates beans: scans @Component, @Service, @Repository, @Controller annotations. When your class has @Autowired, Spring checks its ApplicationContext for a matching bean and injects it. If multiple candidates exist, use @Qualifier("beanName") or @Primary to resolve ambiguity.

Q6. What is the N+1 problem in JPA and how do you solve it? +

Model Answer:

The N+1 problem occurs when fetching a list of entities triggers N additional queries to load their related entities — one query for the parent list plus N queries for the child data. Example: fetch 100 courses (1 query), then access each course's enrollments in a loop — triggers 100 more queries = 101 total queries. This kills database performance. Solutions: (1) JOIN FETCH in JPQL: @Query("SELECT c FROM Course c LEFT JOIN FETCH c.enrollments") — loads everything in ONE query. (2) @EntityGraph: @EntityGraph(attributePaths = {"enrollments"}) on repository method — same effect as JOIN FETCH. (3) Use FetchType.EAGER — loads related entities in the initial query, but avoid this broadly as it can load more data than needed. (4) Batch fetching: @BatchSize(size=25) on the collection — loads children in batches instead of one by one. Detection: enable SQL logging (spring.jpa.show-sql=true) and count queries. Use tools like Hibernate Statistics or p6spy to measure.

Q7. What is a microservice and how is it different from monolithic architecture? +

Model Answer:

A microservice is a small, independently deployable service that focuses on a single business capability and has its own data store. Monolithic architecture packages all functionality (UI, business logic, data access) into a single deployable unit sharing one database. Key differences: Deployment — in a monolith, any change requires redeploying the entire application (risky for large systems). Microservices deploy each service independently. Scaling — monolith scales all-or-nothing. Microservices scale only the bottleneck service. Fault isolation — a bug in monolith can crash everything. A microservice failure is isolated. Technology — monolith uses one tech stack; each microservice can use the most appropriate technology. Complexity trade-off: monolith is simpler to start with, easier to debug, no distributed systems problems. Microservices introduce network latency, distributed transactions (Saga pattern), service discovery (Eureka), API gateway, distributed tracing (Zipkin). Recommendation: start with a monolith, extract microservices when teams grow and specific services need independent scaling.

Q8. Explain the Singleton design pattern. How do you make it thread-safe? +

Model Answer:

The Singleton pattern ensures a class has only ONE instance and provides a global access point to it. Use cases: database connection pool, logging, configuration manager, caching. Basic implementation problems: simple null check is not thread-safe in multi-threaded environments — two threads can both pass the null check simultaneously and create two instances. Thread-safe solutions: (1) Synchronized method: public static synchronized Singleton getInstance() — works but synchronization on every call is expensive. (2) Double-checked locking with volatile: check null outside synchronized block (fast path), check again inside. The volatile keyword ensures the instance is fully constructed before the reference is published (prevents instruction reordering). (3) Bill Pugh Singleton (best practice): use a static inner holder class — class loading is thread-safe by the JVM. The holder class is not loaded until getInstance() is called: private static class Holder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; } This is the cleanest, most efficient thread-safe singleton implementation.

🏅 Certification Guide: For Oracle Certified Professional Java SE 17 (1Z0-829): focus on OOP (40%), Collections & Generics (20%), Exception Handling (10%), Streams & Lambda (15%), Concurrency (10%). For Spring Professional (VMware): Spring Core (DI, IoC), Spring MVC, Spring Data JPA, Spring Security and Spring Boot auto-configuration. These Q&As cover the most tested areas of both exams.

🏫

Ready for Live Java & Spring Boot Training?

Hands-on coding exercises, real project development and personal mentoring from Hari Krishna — 16+ years expert & Silicon India Award Winner.

Get Free Consultation → 💬 WhatsApp Us ← Back to Portal
💬