Java & OOP Fundamentals
Object-Oriented Programming is the foundation of Spring Boot and every Java framework. Master these concepts and you'll understand why Spring works the way it does.
| Feature | What it means for you |
|---|---|
| Platform Independent | Write once, run on Windows/Mac/Linux via JVM |
| Strongly Typed | Errors are caught at compile time, not at 3am in production |
| Object-Oriented | Real-world concepts map to code (User, Order, Product) |
| Massive Ecosystem | Spring, Hibernate, Kafka, Maven โ everything exists |
| Enterprise Adoption | LinkedIn, Uber, Amazon, banks โ all use Java backends |
1. Variables & Data Types
Long (not int) for entity IDs to match database BIGINT. Use String for any text field. Use boolean for flags like isActive, isVerified.2. Conditions
3. Loops
4. Methods (Functions)
5. Constructors
@Entity (JPA) or return objects as JSON (Jackson), your class must have a no-arg constructor. Use @NoArgsConstructor from Lombok to generate it automatically.6. Exception Handling โ Critical for REST APIs
OrderNotFoundException, UserNotFoundException), extend RuntimeException, and use @RestControllerAdvice to catch them globally and return proper HTTP 404 responses.7. String Manipulation โ Used daily in REST APIs
8. Access Modifiers โ Who can see what
| Modifier | Same class | Same package | Subclass | Everywhere | Use in Spring Boot |
|---|---|---|---|---|---|
public | โ | โ | โ | โ | Controller methods, service interfaces, entity getters |
private | โ | โ | โ | โ | Entity fields, internal helper methods |
protected | โ | โ | โ | โ | Base class methods meant for subclasses only |
| (default) | โ | โ | โ | โ | Package-private utilities (rare in Spring) |
private. Service and controller methods โ public. Helper methods that should not be called from outside โ private.Class = blueprint of a house (walls, rooms, doors). Object = the actual house you live in.
You can create many houses (objects) from the same blueprint (class).
๐ Encapsulation
Hide internal data. Expose only what's needed. (private fields + public getters/setters)
๐จโ๐ฉโ๐ฆ Inheritance
Child class inherits fields and methods from parent class. Reuse code. (extends)
๐ญ Polymorphism
One interface, many implementations. Same method name, different behaviour. (overriding)
๐จ Abstraction
Hide complexity. Show only the essential interface. (abstract class, interface)
Method Overriding (Runtime Polymorphism)
Method Overloading (Compile-time Polymorphism)
| Feature | Abstract Class | Interface |
|---|---|---|
| Keyword | abstract class | interface |
| Methods | Can have abstract + concrete methods | All methods abstract by default (Java 8+: can have default methods) |
| Fields | Can have instance variables | Only public static final constants |
| Constructor | Yes | No |
| Inheritance | Single (extends one class) | Multiple (implements many interfaces) |
| Use when | Classes share code (IS-A relationship) | Classes share capability (CAN-DO relationship) |
static keyword
== vs .equals()
Generics (brief introduction)
Collection Hierarchy (memorise this)
List โ When order and index matter
| Class | Backed by | get(i) | add/remove (middle) | Best use case |
|---|---|---|---|---|
| ArrayList | Dynamic array | O(1) โ | O(n) | Read-heavy list, most common choice |
| LinkedList | Doubly linked list | O(n) | O(1) โ | Frequent insert/delete at head or tail |
| Vector | Synchronized array | O(1) | O(n) | Legacy โ use ArrayList in new code |
Set โ When uniqueness matters
| Class | Order | Null | Performance | Use case |
|---|---|---|---|---|
| HashSet | No order | 1 null allowed | O(1) add/contains | Fast uniqueness check โ most common |
| LinkedHashSet | Insertion order | 1 null allowed | O(1) approx | Unique + preserve insertion order |
| TreeSet | Sorted (natural or Comparator) | No null | O(log n) | Unique + sorted (e.g. leaderboard) |
Map โ When you need key โ value lookup
| Class | Order | Null key | Thread-safe? | Use case |
|---|---|---|---|---|
| HashMap | No order | 1 null key โ | No | General purpose โ most common |
| LinkedHashMap | Insertion order | 1 null key โ | No | Cache, LRU cache |
| TreeMap | Sorted by key | No null key | No | Range queries, sorted output |
| Hashtable | No order | No null | Yes (slow) | Legacy โ use ConcurrentHashMap instead |
Collections utility class (java.util.Collections)
List<String> list = new ArrayList<>() not ArrayList<String> list = .... This is called "programming to an interface" and is best practice in Java.Collections Interview Q&A
Use ArrayList when: you access elements by index frequently (get(i) is O(1)), or you mostly add at the end. It's faster for iteration and random access.
Use LinkedList when: you frequently insert or delete at the beginning or middle of the list (O(1) for head/tail). However, in practice, ArrayList is almost always preferred because modern CPUs cache arrays very efficiently.
HashMap uses an array of buckets (internally called a Node array). When you call put(key, value):
- Java calls
key.hashCode()to get an integer hash - The hash is mapped to a bucket index (using modulo on array size)
- The key-value pair is stored in that bucket
- If two keys hash to the same bucket (collision), they're stored as a linked list in the same bucket (Java 8+: becomes a balanced tree when >8 entries)
For get(key): compute hash โ find bucket โ compare keys using equals() โ return value. Average O(1), worst case O(log n) with Java 8 tree bins.
Important: If you use a custom object as a HashMap key, you must override both hashCode() and equals().
HashMap โ Not thread-safe. Allows one null key. Fastest for single-threaded use.
Hashtable โ Thread-safe (synchronized on every method). No null key/value. Legacy โ avoid in new code, it's very slow due to full lock.
ConcurrentHashMap โ Thread-safe but uses segment-level locking (fine-grained), so much faster than Hashtable in concurrent environments. No null key/value. Use this in multi-threaded code.
Fail-fast โ Throws ConcurrentModificationException if the collection is modified during iteration. ArrayList, HashMap use fail-fast iterators. Prevents reading inconsistent data.
Fail-safe โ Iterates on a copy of the collection, so modifications during iteration don't throw an exception. CopyOnWriteArrayList, ConcurrentHashMap use fail-safe iterators. Safe for concurrent reads but uses more memory.
Comparable (java.lang) โ The class itself defines its natural ordering by implementing compareTo(). E.g., String, Integer already implement Comparable. Used by Collections.sort(list) with no extra argument.
Comparator (java.util) โ An external class that defines a custom ordering for any class. Used when you don't own the class or need multiple sort orders.
1. Lambda Expressions โ Anonymous functions
2. Functional Interfaces โ The contract for lambdas
A functional interface has exactly one abstract method. Lambdas implement them. Java 8 added 4 built-in ones in java.util.function:
| Interface | Method | Takes | Returns | Use case |
|---|---|---|---|---|
| Predicate<T> | test(T t) | T | boolean | Filter/check: is age > 18? |
| Function<T,R> | apply(T t) | T | R | Transform: String โ Integer |
| Consumer<T> | accept(T t) | T | void | Side effect: print, save |
| Supplier<T> | get() | nothing | T | Factory/lazy value: () โ new Obj() |
3. Stream API โ The most interviewed Java 8 feature
| Operation | Type | What it does |
|---|---|---|
filter(predicate) | Intermediate | Keep elements matching condition |
map(function) | Intermediate | Transform each element to another type |
flatMap(function) | Intermediate | Flatten nested collections into one stream |
sorted() | Intermediate | Sort elements (natural or Comparator) |
distinct() | Intermediate | Remove duplicates |
limit(n) | Intermediate | Keep only first n elements |
collect() | Terminal | Produce List/Set/Map from stream |
forEach() | Terminal | Perform action on each element |
count() | Terminal | Return number of elements |
reduce() | Terminal | Combine elements into single value |
anyMatch/allMatch | Terminal | Return boolean |
findFirst/findAny | Terminal | Return Optional |
4. Optional โ Avoid NullPointerException
5. Default Methods in Interfaces
6. Method References (::)
A shorthand for a lambda that just calls an existing method.
7. New Date/Time API (java.time)
Java 8 Interview Q&A
A lambda is a concise way to represent an anonymous function โ a block of code you can pass as a parameter. It implements a functional interface.
Problem solved: Before Java 8, passing behaviour required verbose anonymous inner classes. Lambda reduces this to a one-liner: (params) -> expression. This enables functional programming patterns like passing filter/transform logic to Collections and Streams.
map() transforms each element into exactly one other element. The output stream has the same number of elements.
flatMap() transforms each element into a stream of elements and then flattens all those streams into one. Use when each element maps to multiple elements.
Optional<T> is a container that may or may not contain a non-null value. It forces the caller to handle the "no value" case explicitly instead of returning null and risking NullPointerException.
Use it: as a return type from methods that might not find a result (e.g., repository findById() returns Optional<User>).
Don't use it: as a field type, constructor parameter, or method parameter โ that's an anti-pattern. Optional is for return types only.
Intermediate operations (filter, map, sorted, distinct, limit) return a new Stream. They are lazy โ they don't execute until a terminal operation is called. You can chain multiple intermediate ops.
Terminal operations (collect, forEach, count, reduce, findFirst, anyMatch) trigger the pipeline to execute and produce a result or side effect. Once called, the stream is consumed and cannot be reused.
This is the most common type of coding question asked about Java 8. Practice writing these from scratch.
- Lambda expressions โ anonymous functions, enables functional programming
- Stream API โ functional-style processing of collections
- Optional<T> โ explicit null handling
- Default and static methods in interfaces โ add methods to interfaces without breaking implementations
- Method references (::) โ shorthand for lambdas that call existing methods
- java.time API โ new Date/Time API (LocalDate, LocalDateTime, etc.)
- Functional interfaces โ Predicate, Function, Consumer, Supplier in java.util.function
Encapsulation โ Wrapping data (fields) and methods into a single unit (class) and restricting direct access to data using access modifiers (private). Expose data through public getters/setters.
Inheritance โ A child class acquires properties and behaviour of a parent class using extends. Promotes code reuse. Java supports single class inheritance.
Polymorphism โ "One interface, many implementations." Method overriding (runtime) and method overloading (compile-time). Allows treating different objects uniformly through a common interface.
Abstraction โ Hiding implementation details and exposing only the necessary interface. Achieved through abstract classes and interfaces.
Overloading โ Same method name, different parameter list (number, type, or order). Happens in the same class. Resolved at compile time (static polymorphism).
Overriding โ Same method name and signature in a child class that re-implements the parent's method. Resolved at runtime (dynamic polymorphism). Requires @Override annotation.
Use an abstract class when classes share code and have a common identity (IS-A). A Dog and Cat both IS-A Animal and share breathe() logic.
Use an interface when unrelated classes share a capability (CAN-DO). A Duck and Airplane both CAN fly โ they're not related, but they share the Flyable interface.
Key difference: A class can extend only one abstract class but can implement multiple interfaces.
== checks reference equality โ whether two variables point to the same object in memory. For primitives (int, boolean), it compares values.
.equals() checks content equality โ whether two objects have the same value. The String class overrides equals() to compare character sequences.
Always use .equals() to compare String and other objects. Use == only for primitives or when checking if two references are literally the same object.
A constructor is a special method called when an object is created with new. It has the same name as the class and no return type. It initializes the object's fields.
Yes, a constructor can be private. This is used in the Singleton design pattern โ when you want exactly one instance of a class to exist. The class controls its own instantiation through a static factory method.
The static keyword means the member belongs to the class itself, not to any specific instance. You don't need to create an object to use it.
- Static field โ shared by all instances. E.g., a counter of how many objects were created.
- Static method โ can be called on the class directly. E.g.,
Math.sqrt(),Arrays.sort(). - Static block โ runs once when the class is first loaded.
Encapsulation hides internal state and allows controlled access through public methods. It solves the problem of invalid state.
Without encapsulation, anyone could set account.balance = -1000000 directly. With encapsulation, your withdraw() method validates the amount before modifying the balance โ the object always stays in a valid state.