***1. Difference between abstract class and interface
Collections Framework Deep Dive
***27. Why are Strings immutable?
In Java, String objects are immutable, which means once a string object is created, its value cannot be changed.
Example
String s = "Java";
s.concat(" Programming");
System.out.println(s);
Output:
Java
A new object is created instead of modifying the existing one.
Reasons Why Strings are Immutable
1. Security
Strings are heavily used in:
- database URLs
- file paths
- network connections
- class loading
Immutability prevents accidental or malicious modification.
2. String Pool Optimization
String literals are shared in:
String Constant Pool
Immutability allows multiple references to safely use the same object.
Example
String a = "Java";
String b = "Java";
Both point to same pooled object.
3. Thread Safety
Immutable objects are naturally thread-safe because their state cannot change.
No synchronization required.
4. HashCode Caching
Strings are commonly used as keys in:
- HashMap
- Hashtable
Immutability guarantees hashcode consistency.
5. Performance Improvement
String Pool reduces duplicate object creation.
Important Interview Point:
If Strings were mutable, changing one reference could unintentionally affect many other references pointing to the same pooled object.
***28. Benefits of immutable classes
Immutable classes provide many advantages in Java applications.
What is an Immutable Class?
An immutable class is a class whose objects cannot change after creation.
Example:
String
Benefits of Immutable Classes
1. Thread Safety
Immutable objects are automatically thread-safe.
No synchronization needed.
2. Security
Sensitive data cannot be modified after object creation.
Useful for:
- passwords
- configuration objects
- cache keys
3. Simplicity
Objects remain in consistent state.
No unexpected modifications.
4. Safe Sharing
Multiple threads can safely share same object.
5. Better Hashing
Immutable objects are reliable keys for:
HashMap
because hashcode remains constant.
6. Easier Debugging
Object state never changes, making debugging easier.
Real Examples
- String
- Integer
- LocalDate
Important Interview Point:
Immutable classes are widely used in concurrent programming because they eliminate synchronization problems.
**29. How to create immutable class in Java?
An immutable class ensures object state cannot change after creation.
Steps to Create Immutable Class
1. Declare class as final
Prevents inheritance.
2. Make fields private and final
Fields cannot be modified directly.
3. Initialize fields through constructor
4. Do not provide setter methods
5. Return defensive copies for mutable objects
Example
final class Employee {
private final int id;
private final String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
Features of Above Class
- Cannot be inherited
- Fields cannot change
- No setter methods
Defensive Copy Example
return new Date(date.getTime());
Used for mutable fields like Date.
Important Interview Point:
Making fields final alone does not guarantee immutability if mutable objects are exposed directly.
**30. Difference between StringBuilder and StringBuffer performance
Both StringBuilder and StringBuffer are mutable string classes, but they differ in synchronization and performance.
StringBuffer
- Thread-safe
- Methods are synchronized
Example
StringBuffer sb = new StringBuffer();
StringBuilder
- Not thread-safe
- No synchronization
Example
StringBuilder sb = new StringBuilder();
Performance Difference
Because StringBuffer uses synchronization:
- additional locking overhead occurs
- execution becomes slower
StringBuilder avoids synchronization, so it is faster.
Difference Table
| Feature | StringBuffer | StringBuilder |
|---|---|---|
| Thread Safe | Yes | No |
| Synchronization | Yes | No |
| Performance | Slower | Faster |
| Introduced In | Java 1.0 | Java 1.5 |
When to Use
| Situation | Recommended |
|---|---|
| Multithreaded environment | StringBuffer |
| Single-threaded environment | StringBuilder |
Important Interview Point:
In modern applications, StringBuilder is preferred unless thread safety is required.
*31. Explain String interning
String interning is the process of storing only one copy of identical string literals in the String Pool.
Purpose
- Save memory
- Improve performance
- Reuse string objects
Example
String s1 = "Java";
String s2 = "Java";
Both references point to same pooled object.
Internal Working
When JVM encounters a string literal:
- Checks String Pool
- If string exists → reuse reference
- Otherwise → create new object in pool
Example with new Keyword
String s1 = new String("Java");
String s2 = s1.intern();
intern() returns pooled reference.
String Pool Behavior
String a = "Java";
String b = new String("Java");
System.out.println(a == b);
Output:
false
Because:
-
a→ String Pool -
b→ Heap object
Using intern()
String c = b.intern();
System.out.println(a == c);
Output:
true
Advantages
- Reduces duplicate objects
- Saves heap memory
- Improves performance
Important Interview Point:
Only string literals are automatically interned. Objects created using new String() are not pooled unless intern() is called.
***32. Custom exceptions in Java
Custom exceptions are user-defined exceptions created to represent application-specific errors.
They help provide meaningful error handling.
Why Custom Exceptions Are Needed
Built-in exceptions may not clearly represent business logic errors.
Example:
- Invalid employee ID
- Insufficient balance
- Age restriction violation
How to Create Custom Exception
Create a class extending:
-
Exception→ checked exception
or -
RuntimeException→ unchecked exception
Example
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
Using Custom Exception
class Test {
static void validateAge(int age)
throws InvalidAgeException {
if(age < 18) {
throw new InvalidAgeException(
"Not eligible to vote"
);
}
}
public static void main(String[] args) {
try {
validateAge(15);
}
catch(InvalidAgeException e) {
System.out.println(e.getMessage());
}
}
}
Advantages
- Better readability
- Business-specific handling
- Cleaner code design
Important Interview Point:
Use checked exceptions for recoverable conditions and unchecked exceptions for programming errors.
***33. Difference between checked and unchecked exceptions with examples
Java exceptions are categorized into:
- Checked Exceptions
- Unchecked Exceptions
Checked Exceptions
Checked at:
Compile Time
Compiler forces handling.
Examples
- IOException
- SQLException
- FileNotFoundException
Example
FileReader file =
new FileReader("test.txt");
Compiler requires:
- try-catch
or - throws
Unchecked Exceptions
Occur at:
Runtime
Compiler does not force handling.
Examples
- NullPointerException
- ArithmeticException
- ArrayIndexOutOfBoundsException
Example
int x = 10 / 0;
Difference Table
| Feature | Checked Exception | Unchecked Exception |
|---|---|---|
| Checked By | Compiler | JVM |
| Handling Mandatory | Yes | No |
| Occurs At | Compile time | Runtime |
| Parent Class | Exception | RuntimeException |
Hierarchy
Throwable
├── Exception
│ ├── Checked Exceptions
│ └── RuntimeException
│ └── Unchecked Exceptions
└── Error
Important Interview Point:
Unchecked exceptions usually indicate programming mistakes.
***34. Can we have try without catch?
Yes, a try block can exist without catch, but it must be followed by:
finally
Valid Syntax
try {
System.out.println("Try block");
}
finally {
System.out.println("Finally block");
}
Invalid Syntax
try {
}
This causes compile-time error because:
- either
catch
or -
finally
is mandatory.
Why Use try-finally?
Used mainly for:
- resource cleanup
- file closing
- database connection release
Important Interview Point:
A try block must always be followed by at least one:
-
catch
or -
finally
block.
**35. What happens if return statement exists in try and finally?
If both try and finally contain return statements, the finally block return overrides the try block return.
Example
class Test {
static int test() {
try {
return 10;
}
finally {
return 20;
}
}
public static void main(String[] args) {
System.out.println(test());
}
}
Output
20
Why?
finally block always executes before method completes.
Important Warning
Returning from finally is considered:
Bad Practice
because it may:
- hide exceptions
- confuse debugging
Important Interview Point:
finally execution has higher priority than try return.
**36. What is multi-catch block?
A multi-catch block allows handling multiple exception types in a single catch block.
Introduced in:
Java 7
Syntax
catch(ExceptionType1 | ExceptionType2 e)
Example
try {
int[] arr = new int[5];
arr[10] = 50;
}
catch(ArrayIndexOutOfBoundsException |
ArithmeticException e) {
System.out.println("Exception handled");
}
Advantages
- Reduces duplicate code
- Cleaner exception handling
- Better readability
Important Rule
Exceptions in multi-catch must NOT have parent-child relationship.
Invalid Example
catch(Exception | IOException e)
Because:
IOException is subclass of Exception
Important Interview Point:
The exception variable in multi-catch is implicitly final.
**37. What is try-with-resources?
try-with-resources automatically closes resources after usage.
Introduced in:
Java 7
Purpose
Simplifies resource management.
Resources Commonly Used
- File streams
- Database connections
- BufferedReader
- Scanner
Example
try(BufferedReader br =
new BufferedReader(
new FileReader("test.txt"))) {
System.out.println(br.readLine());
}
catch(IOException e) {
e.printStackTrace();
}
Internal Working
Resources implementing:
AutoCloseable
are automatically closed.
Advantages
- Cleaner code
- Prevents resource leaks
- No need for finally block
Before Java 7
Resources closed manually using:
finally
Important Interview Point:
try-with-resources reduces boilerplate code significantly.
*38. What is suppressed exception?
A suppressed exception occurs when:
- one exception is thrown in
try
and - another exception occurs while closing resources
The second exception becomes:
Suppressed Exception
Example Scenario
- Exception occurs in try block
- Resource closing also throws exception
- Original exception preserved
- Closing exception suppressed
Example
try(MyResource r = new MyResource()) {
throw new Exception("Main Exception");
}
If close() also throws exception:
- JVM suppresses close exception
Accessing Suppressed Exceptions
exception.getSuppressed();
Why Important?
Before Java 7:
- original exceptions could be lost
Try-with-resources preserves them safely.
Important Interview Point:
Suppressed exceptions are mainly associated with:
try-with-resources
***39. Difference between synchronized method and synchronized block
Both are used for thread synchronization, but they differ in scope and flexibility.
Synchronized Method
Entire method becomes synchronized.
Example
synchronized void display() {
System.out.println("Thread-safe method");
}
Lock Applied On
- Current object (
this) for instance methods - Class object for static methods
Synchronized Block
Only a specific block of code is synchronized.
Example
void display() {
synchronized(this) {
System.out.println("Critical section");
}
}
Advantages
- Better performance
- Smaller locking scope
- More flexibility
Difference Table
| Feature | Synchronized Method | Synchronized Block |
|---|---|---|
| Lock Scope | Entire method | Specific block |
| Performance | Slower | Faster |
| Flexibility | Less | More |
| Lock Control | Automatic | Custom object possible |
Important Interview Point:
Synchronized blocks are preferred because they reduce lock contention.
***40. What is synchronization and why is it needed?
Synchronization is a mechanism that controls access to shared resources by multiple threads.
It ensures:
Only one thread accesses critical section at a time
Why Synchronization is Needed
Without synchronization:
- data inconsistency may occur
- race conditions may happen
Example Without Synchronization
count++;
Multiple threads may update incorrect values simultaneously.
Example With Synchronization
synchronized void increment() {
count++;
}
Benefits
- Prevents race conditions
- Maintains data consistency
- Ensures thread safety
Drawback
- Performance overhead due to locking
Important Interview Point:
Synchronization mainly protects:
Critical Sections
of code.
***41. Difference between wait(), notify(), and notifyAll()
These methods are used for:
Inter-thread communication
Defined in:
Object class
wait()
Causes current thread to:
- release lock
- enter waiting state
Example
obj.wait();
notify()
Wakes up:
One waiting thread
Example
obj.notify();
notifyAll()
Wakes up:
All waiting threads
Example
obj.notifyAll();
Difference Table
| Method | Purpose |
|---|---|
| wait() | Releases lock and waits |
| notify() | Wakes one waiting thread |
| notifyAll() | Wakes all waiting threads |
Important Rules
- Must be called inside synchronized block
- Operate on object monitor
Important Interview Point:
wait() releases lock, while sleep() does not.
***42. What is deadlock?
Deadlock occurs when two or more threads wait indefinitely for each other’s resources.
As a result:
Program execution stops permanently
Example Scenario
Thread 1
Holds Lock A and waits for Lock B.
Thread 2
Holds Lock B and waits for Lock A.
Neither thread proceeds.
Example
Thread 1:
synchronized(lockA) {
synchronized(lockB) {
}
}
Thread 2:
synchronized(lockB) {
synchronized(lockA) {
}
}
Conditions for Deadlock
1. Mutual Exclusion
Only one thread uses resource at a time.
2. Hold and Wait
Thread holds one resource and waits for another.
3. No Preemption
Resources cannot be forcefully taken away.
4. Circular Wait
Threads form circular dependency.
Prevention Techniques
- Lock ordering
- Timeout locks
- Avoid nested synchronization
Important Interview Point:
Deadlocks are difficult to debug in large concurrent applications.
***43. What is race condition?
A race condition occurs when multiple threads access and modify shared data simultaneously, causing unpredictable results.
Example
count++;
This operation is not atomic.
Problem
Two threads may:
- read same value
- modify simultaneously
- overwrite updates
Example Scenario
Initial value:
count = 5
Two threads increment simultaneously.
Expected:
7
Actual:
6
Causes
- Shared mutable data
- Lack of synchronization
Prevention
- synchronized
- locks
- atomic variables
Important Interview Point:
Race conditions are one of the most common multithreading bugs.
***44. What is volatile keyword?
volatile ensures visibility of variable changes across threads.
Purpose
When one thread updates variable value:
- other threads immediately see updated value
Example
volatile boolean flag = true;
Without volatile
Threads may cache old value locally.
With volatile
Variable always read from:
Main Memory
Important Features
- Guarantees visibility
- Prevents instruction reordering
- Does NOT provide full synchronization
Limitation
Operations like:
count++;
are still not thread-safe.
Use Cases
- Status flags
- Shutdown signals
- Configuration updates
Important Interview Point:
volatile provides visibility, not atomicity.
**45. What is ThreadLocal?
ThreadLocal provides separate copies of variables for each thread.
Each thread gets:
Its own independent value
Example
ThreadLocal<Integer> local =
new ThreadLocal<>();
Setting Value
local.set(100);
Getting Value
local.get();
Advantages
- Avoids shared data conflicts
- No synchronization needed
- Thread-safe storage
Common Use Cases
- Database connections
- User sessions
- Transaction management
Important Interview Point:
Each thread maintains its own isolated ThreadLocal value.
**46. Callable vs Runnable
Both represent tasks executed by threads.
Runnable
Introduced in:
Java 1.0
Features
- No return value
- Cannot throw checked exceptions
Method
run()
Callable
Introduced in:
Java 5
Features
- Returns value
- Can throw exceptions
Method
call()
Example
Callable<Integer> task = () -> {
return 100;
};
Difference Table
| Feature | Runnable | Callable |
|---|---|---|
| Return Value | No | Yes |
| Checked Exception | No | Yes |
| Method | run() | call() |
| Introduced | Java 1.0 | Java 5 |
Important Interview Point:
Callable tasks are executed using:
ExecutorService
and return:
Future
objects.
**47. ExecutorService in Java
ExecutorService is a framework for managing and executing threads efficiently.
Defined in:
java.util.concurrent
Purpose
- Reuse threads
- Manage thread lifecycle
- Improve performance
Example
ExecutorService service =
Executors.newFixedThreadPool(3);
Submitting Task
service.submit(() -> {
System.out.println("Task running");
});
Shutdown
service.shutdown();
Advantages
- Better resource management
- Reduces thread creation overhead
- Supports thread pools
Common Methods
| Method | Purpose |
|---|---|
| submit() | Submit task |
| execute() | Execute Runnable |
| shutdown() | Stop executor |
Important Interview Point:
ExecutorService is preferred over manual thread creation in enterprise applications.
**48. What is thread pool?
A thread pool is a collection of reusable worker threads managed by JVM.
Why Thread Pool is Needed
Creating threads repeatedly is expensive.
Thread pool:
- reuses existing threads
- improves performance
- reduces memory overhead
Working Process
Step 1
Threads created in advance.
Step 2
Tasks submitted to queue.
Step 3
Available thread executes task.
Example
ExecutorService service =
Executors.newFixedThreadPool(5);
Types of Thread Pools
| Pool Type | Description |
|---|---|
| FixedThreadPool | Fixed number of threads |
| CachedThreadPool | Dynamic threads |
| SingleThreadExecutor | One thread only |
| ScheduledThreadPool | Scheduled tasks |
Advantages
- Better performance
- Reduced thread creation cost
- Controlled concurrency
Important Interview Point:
Thread pools are widely used in:
- web servers
- enterprise applications
- microservices
- asynchronous processing
*49. What is ReentrantLock?
ReentrantLock is a locking mechanism from:
java.util.concurrent.locks
It provides explicit locking with more flexibility than synchronized.
Why It Is Called Reentrant
The same thread can acquire the same lock multiple times without deadlock.
Example
ReentrantLock lock =
new ReentrantLock();
lock.lock();
try {
System.out.println("Critical section");
}
finally {
lock.unlock();
}
Features
- Explicit locking
- Better thread control
- Fair locking support
- Interruptible locking
- Try-lock capability
Important Methods
| Method | Purpose |
|---|---|
| lock() | Acquire lock |
| unlock() | Release lock |
| tryLock() | Try acquiring lock |
| lockInterruptibly() | Interruptible locking |
Difference from synchronized
| Feature | synchronized | ReentrantLock |
|---|---|---|
| Lock Control | Automatic | Manual |
| Fairness Policy | No | Yes |
| tryLock() Support | No | Yes |
| Interruptible | No | Yes |
Important Interview Point:
Always release ReentrantLock inside:
finally
to avoid deadlocks.
Java 8 Features
***50. What are lambda expressions?
Lambda expressions provide a concise way to write anonymous functions.
Introduced in:
Java 8
Purpose
- Reduce boilerplate code
- Support functional programming
- Simplify anonymous classes
Syntax
(parameters) -> expression
Example
Runnable r = () -> {
System.out.println("Running");
};
Before Lambda
Runnable r = new Runnable() {
public void run() {
System.out.println("Running");
}
};
Advantages
- Cleaner code
- Improved readability
- Easier collection processing
Common Use Cases
- Streams API
- Event handling
- Multithreading
Important Interview Point:
Lambda expressions work mainly with:
Functional Interfaces
***51. What is functional interface?
A functional interface is an interface containing exactly:
One abstract method
Used mainly with:
- lambda expressions
- method references
Example
@FunctionalInterface
interface Calculator {
int add(int a, int b);
}
Features
- Can contain default/static methods
- Only one abstract method allowed
Common Functional Interfaces
| Interface | Purpose |
|---|---|
| Runnable | No input/output |
| Callable | Returns value |
| Predicate | Boolean result |
| Function | Input → Output |
| Consumer | Consumes input |
Example Using Lambda
Calculator c = (a, b) -> a + b;
Important Interview Point:
@FunctionalInterface annotation is optional but recommended.
***52. What is Stream API?
Stream API is used for processing collections of data declaratively.
Introduced in:
Java 8
Purpose
- Simplify collection operations
- Support functional programming
- Enable parallel processing
Features
- Functional style
- Lazy evaluation
- Internal iteration
Example
List<Integer> list =
Arrays.asList(1,2,3,4,5);
list.stream()
.filter(x -> x % 2 == 0)
.forEach(System.out::println);
Common Stream Operations
| Operation | Purpose |
|---|---|
| filter() | Select elements |
| map() | Transform data |
| sorted() | Sorting |
| collect() | Collect results |
| forEach() | Iterate elements |
Stream Types
Intermediate Operations
Return stream.
Examples:
- filter()
- map()
Terminal Operations
Produce final result.
Examples:
- collect()
- count()
Important Interview Point:
Streams do not modify original collection.
***53. Difference between map() and flatMap()
Both are Stream API operations used for transformation.
map()
Transforms each element individually.
Example
List<String> names =
Arrays.asList("java", "python");
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
flatMap()
Transforms and flattens nested structures into single stream.
Example
List<List<Integer>> list =
Arrays.asList(
Arrays.asList(1,2),
Arrays.asList(3,4)
);
list.stream()
.flatMap(x -> x.stream())
.forEach(System.out::println);
Difference Table
| Feature | map() | flatMap() |
|---|---|---|
| Output | One-to-one mapping | Flattened mapping |
| Structure | Preserves nesting | Removes nesting |
| Use Case | Simple transformation | Nested collections |
Important Interview Point:
flatMap() is heavily used in nested collection processing.
***54. What is Optional class?
Optional is a container object introduced in Java 8 to handle:
Null values safely
Purpose
Reduce:
NullPointerException
Example
Optional<String> name =
Optional.of("Java");
Common Methods
| Method | Purpose |
|---|---|
| of() | Create non-null Optional |
| ofNullable() | Allow null |
| isPresent() | Check value |
| get() | Retrieve value |
| orElse() | Default value |
Example
String result =
Optional.ofNullable(null)
.orElse("Default");
Advantages
- Cleaner null handling
- Reduces null checks
- Improves readability
Important Interview Point:
Avoid excessive use of:
get()
without checking presence.
**55. What are method references?
Method references provide shorthand syntax for lambda expressions that call existing methods.
Syntax
ClassName::methodName
Example
list.forEach(System.out::println);
Equivalent lambda:
list.forEach(x -> System.out.println(x));
Types of Method References
| Type | Example |
|---|---|
| Static Method | Math::abs |
| Instance Method | obj::display |
| Constructor Reference | Student::new |
Advantages
- Cleaner syntax
- Better readability
- Less boilerplate
Important Interview Point:
Method references are valid only when lambda simply calls another method.
**56. Difference between Collection stream() and parallelStream()
Both create streams, but execution differs.
stream()
Processes elements sequentially.
Example
list.stream()
parallelStream()
Processes elements in parallel using multiple threads.
Example
list.parallelStream()
Difference Table
| Feature | stream() | parallelStream() |
|---|---|---|
| Execution | Sequential | Parallel |
| Threads Used | Single | Multiple |
| Performance | Better for small tasks | Better for large CPU tasks |
| Order | Maintained | May vary |
Internal Working
parallelStream() uses:
ForkJoinPool
Important Interview Point:
Parallel streams may reduce performance for small collections because of thread overhead.
**57. What is default method in interface?
Default methods allow interfaces to contain method implementations.
Introduced in:
Java 8
Purpose
Enable adding new methods to interfaces without breaking existing implementations.
Example
interface Vehicle {
default void start() {
System.out.println("Vehicle Started");
}
}
Features
- Provides implementation inside interface
- Inheritable by implementing classes
Why Needed
Before Java 8:
adding method to interface would break all implementing classes.
Important Interview Point:
Default methods help achieve backward compatibility.
*58. What is Nashorn engine?
Nashorn is a JavaScript engine introduced in:
Java 8
It allows Java applications to execute JavaScript code.
Package
javax.script
Example
ScriptEngineManager manager =
new ScriptEngineManager();
ScriptEngine engine =
manager.getEngineByName("nashorn");
engine.eval("print('Hello')");
Features
- Lightweight JavaScript execution
- JVM integration
- Better performance than Rhino
Status
Nashorn was:
- deprecated in Java 11
- removed in Java 15
Important Interview Point:
Nashorn enabled seamless Java and JavaScript interoperability inside JVM.
Serialization
***59. What is serialization and deserialization?
Serialization is the process of converting an object into a byte stream so it can be:
- stored in file
- transferred over network
- saved in database
Deserialization is the reverse process of converting byte stream back into object.
Why Serialization is Used
- Object persistence
- Network communication
- Distributed systems
- Caching
Serialization Process
Object → Byte Stream
Deserialization Process
Byte Stream → Object
Example
Serialization
ObjectOutputStream out =
new ObjectOutputStream(
new FileOutputStream("data.ser"));
out.writeObject(obj);
Deserialization
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream("data.ser"));
Student s = (Student) in.readObject();
Important Classes
| Class | Purpose |
|---|---|
| ObjectOutputStream | Serialize object |
| ObjectInputStream | Deserialize object |
Advantages
- Easy object storage
- Simplifies data transfer
- Supports distributed computing
Important Interview Point:
Only objects implementing:
Serializable
can be serialized.
***60. What is Serializable interface?
Serializable is a marker interface used to indicate that an object can be serialized.
Defined in:
java.io
Why It Is Called Marker Interface
Because it contains:
No methods
Example
import java.io.Serializable;
class Student implements Serializable {
int id;
String name;
}
Purpose
JVM checks whether class implements:
Serializable
before serialization.
What Happens If Not Implemented?
JVM throws:
NotSerializableException
Features
- Enables serialization
- Supports object persistence
- Used in distributed systems
Important Interview Point:
All non-transient instance variables are serialized automatically.
**61. How to prevent serialization of fields?
Fields can be prevented from serialization using:
transient
keyword.
Example
class Student implements Serializable {
int id;
transient String password;
}
Serialization Result
-
id→ serialized -
password→ skipped
Why Use transient?
Sensitive or temporary data should not be stored.
Common Use Cases
- Passwords
- OTPs
- Security tokens
- Temporary cache data
After Deserialization
Transient fields get:
Default values
Example:
null, 0, false
Important Interview Point:
static variables are also not serialized because they belong to class, not object.
**62. What is serialVersionUID?
serialVersionUID is a unique identifier used during serialization and deserialization.
It verifies compatibility between:
- serialized object
- loaded class
Example
class Student implements Serializable {
private static final long
serialVersionUID = 1L;
}
Why It Is Needed
Suppose:
- Object serialized using old class version
- Class structure changes later
JVM compares:
serialVersionUID
If mismatch occurs:
InvalidClassException
is thrown.
Benefits
- Version control for serialized objects
- Prevents compatibility issues
- Improves reliability
If Not Declared
JVM generates automatically.
But generated value may change unexpectedly.
Important Interview Point:
Always declare explicit:
serialVersionUID
in serializable classes.
*63. Difference between Externalizable and Serializable
Both are used for object serialization, but they differ in control and implementation.
Serializable
Java automatically handles serialization.
Example
class Student implements Serializable {
}
Features
- Easy to use
- Automatic serialization
- Less control
Externalizable
Provides complete control over serialization process.
Extends:
Serializable
Example
class Student implements Externalizable {
public void writeExternal(
ObjectOutput out)
throws IOException {
out.writeInt(id);
}
public void readExternal(
ObjectInput in)
throws IOException {
id = in.readInt();
}
}
Required Methods
| Method | Purpose |
|---|---|
| writeExternal() | Custom serialization |
| readExternal() | Custom deserialization |
Difference Table
| Feature | Serializable | Externalizable |
|---|---|---|
| Control | Automatic | Manual |
| Performance | Slower | Faster |
| Ease of Use | Simple | Complex |
| Methods Required | No | Yes |
| Constructor Requirement | No | Public no-arg required |
When to Use
| Situation | Recommended |
|---|---|
| Simple serialization | Serializable |
| Customized high-performance serialization | Externalizable |
Important Interview Point:
Externalizable gives full control but increases coding responsibility.
***71. What is dependency injection?
Dependency Injection (DI) is a design pattern where dependencies are provided to an object externally instead of the object creating them itself.
Purpose
- Reduce tight coupling
- Improve testability
- Increase flexibility
Without Dependency Injection
class Car {
Engine engine = new Engine();
}
Car creates dependency itself.
This causes:
Tight Coupling
With Dependency Injection
class Car {
private Engine engine;
Car(Engine engine) {
this.engine = engine;
}
}
Dependency provided externally.
Types of Dependency Injection
| Type | Description |
|---|---|
| Constructor Injection | Dependency through constructor |
| Setter Injection | Dependency through setter |
| Field Injection | Dependency directly into field |
Advantages
- Loose coupling
- Easier unit testing
- Better maintainability
Frameworks Using DI
- Spring Framework
- Jakarta EE
Important Interview Point:
Dependency Injection follows:
Inversion of Control (IoC)
principle.
***72. What is Singleton design pattern?
Singleton Pattern ensures:
Only one object
of a class exists throughout application lifecycle.
Purpose
Used when exactly one shared instance is required.
Common Use Cases
- Logger
- Database connection manager
- Configuration manager
- Cache manager
Key Features
- Private constructor
- Static instance
- Global access point
Example
class Singleton {
private static Singleton instance =
new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
Advantages
- Controlled object creation
- Shared resource management
- Saves memory
Important Interview Point:
Singleton pattern is one of the most commonly asked Java design pattern interview questions.
***73. How to implement Singleton in Java?
There are multiple ways to implement Singleton in Java.
1. Eager Initialization
Object created immediately.
Example
class Singleton {
private static final Singleton instance =
new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
Advantages
- Simple
- Thread-safe
Disadvantage
Object created even if unused.
2. Lazy Initialization
Object created only when needed.
Example
class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
Problem
Not thread-safe.
3. Thread-Safe Singleton
Using synchronized method.
Example
public synchronized static
Singleton getInstance() {
}
4. Bill Pugh Singleton (Recommended)
Uses static inner helper class.
Example
class Singleton {
private Singleton() {
}
private static class Helper {
private static final Singleton INSTANCE =
new Singleton();
}
public static Singleton getInstance() {
return Helper.INSTANCE;
}
}
5. Enum Singleton (Best Approach)
Example
enum Singleton {
INSTANCE;
}
Important Interview Point:
Enum Singleton is safest because it prevents:
- reflection attacks
- serialization issues
***74. What are immutable objects?
Immutable objects are objects whose state cannot be changed after creation.
Example
String s = "Java";
Strings are immutable.
Features
- State never changes
- Thread-safe
- Easy to share
How to Create Immutable Object
Rules
- Make class final
- Make fields private and final
- No setter methods
- Initialize through constructor
Example
final class Employee {
private final int id;
Employee(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
Advantages
- Thread safety
- Security
- Simpler design
Important Interview Point:
Immutable objects are heavily used in concurrent programming.
**75. What are Java design patterns?
Design patterns are reusable solutions to commonly occurring software design problems.
Purpose
- Improve code structure
- Promote best practices
- Increase maintainability
Categories of Design Patterns
| Category | Purpose |
|---|---|
| Creational | Object creation |
| Structural | Object composition |
| Behavioral | Object interaction |
Common Java Design Patterns
| Pattern | Category |
|---|---|
| Singleton | Creational |
| Factory | Creational |
| Builder | Creational |
| Adapter | Structural |
| Observer | Behavioral |
Advantages
- Reusable solutions
- Better architecture
- Easier maintenance
Important Interview Point:
Design patterns are not code, but proven design solutions.
**76. Explain Factory Design Pattern
Factory Pattern creates objects without exposing object creation logic to client.
Purpose
Object creation delegated to factory class.
Example Without Factory
Car c = new Car();
Client directly creates object.
With Factory Pattern
class VehicleFactory {
static Vehicle getVehicle(String type) {
if(type.equals("car")) {
return new Car();
}
return new Bike();
}
}
Usage
Vehicle v =
VehicleFactory.getVehicle("car");
Advantages
- Loose coupling
- Centralized object creation
- Easy scalability
Real-Life Example
Shape Factory
creates:
- Circle
- Rectangle
- Square
Important Interview Point:
Factory Pattern hides object creation complexity from client.
**77. Explain Builder Pattern
Builder Pattern is used to construct complex objects step by step.
Why Needed
Suppose constructor has many parameters:
new Student(1, "A", 20, "Patna", true)
Hard to read and maintain.
Builder Solution
Example
class Student {
private int id;
private String name;
private Student(Builder b) {
this.id = b.id;
this.name = b.name;
}
static class Builder {
private int id;
private String name;
Builder setId(int id) {
this.id = id;
return this;
}
Builder setName(String name) {
this.name = name;
return this;
}
Student build() {
return new Student(this);
}
}
}
Usage
Student s = new Student.Builder()
.setId(1)
.setName("Java")
.build();
Advantages
- Readable object creation
- Flexible construction
- Avoids telescoping constructors
Important Interview Point:
Builder Pattern is commonly used in:
- Lombok
- StringBuilder
- Java APIs
78. Explain Observer Pattern
Observer Pattern defines:
One-to-many dependency
When one object changes state, all dependent objects are notified automatically.
Components
| Component | Role |
|---|---|
| Subject | Main object |
| Observer | Dependent objects |
Real-Life Example
YouTube Channel Subscription
When creator uploads video:
- all subscribers notified
Example
interface Observer {
void update();
}
Subject
class YouTubeChannel {
List<Observer> observers =
new ArrayList<>();
void subscribe(Observer o) {
observers.add(o);
}
void notifyUsers() {
for(Observer o : observers) {
o.update();
}
}
}
Advantages
- Loose coupling
- Event-driven communication
- Easy scalability
Common Use Cases
- Event listeners
- GUI frameworks
- Notification systems
Important Interview Point:
Observer Pattern is heavily used in:
- Java event handling
- Reactive programming
- Messaging systems