In Java
In Java
.equals() checks if two objects are considered equal by their value/content (as defined by the
class’s equals method).
Java
Integer a = 127;
Integer b = 127;
[Link](a == b); // true
[Link]([Link](b)); // true
Integer a = 128;
Integer b = 128;
[Link](a == b); // false
[Link]([Link](b)); // true
This happens because Java caches Integer objects for values from -128 to 127. Integer variables within this range
refer to the same object when created using valueOf() (default for autoboxing), hence == returns true. Outside this
range, new Integer objects are created, so == returns false.
What is the difference between abstraction and encapsulation in Java? Explain with examples.
Abstraction:
Definition: Abstraction is the concept of showing only essential details to the user and hiding the
implementation details.
Example: Abstract classes and interfaces let you declare methods that must be implemented by subclasses,
while the specific implementation is hidden.
Usage: Use abstract classes or interfaces when you want to define a contract or functionality without
specifying the details.
Java
abstract class Animal {
abstract void eat(); // abstraction: we don’t say HOW animals eat
}
class Dog extends Animal {
void eat() { [Link]("Dog eats bones"); } // concrete
implementation
}
Encapsulation:
Definition: Encapsulation means wrapping data (fields) and code (methods) together in a class, and
controlling access to them.
Example: Using private fields and public getter/setter methods so the internal state can’t be accessed directly.
Usage: Protects the internal state and only allows it to be changed in a controlled manner (through methods).
Java
class Person {
private String name;
public String getName() { return name; }
public void setName(String name) { [Link] = name; }
}
Access modifiers:
You understand abstraction hides implementation, lets you specify what (not how)
You understand encapsulation means bundling data and restricting access—using access modifiers
What is Polymorphism in Java? Can you give two types and a real-life code example?
Polymorphism:
Definition: Polymorphism allows objects to be treated as instances of their parent class, enabling a single
interface with multiple implementations.
Types:
Multiple methods with the same name but different parameter lists (number, type, or both).
Example:
Java
class MathUtil {
int add(int a, int b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
}
i. Run-time polymorphism (Method Overriding):
Example:
Java
class Animal {
void speak() { [Link]("Animal speaks"); }
}
class Dog extends Animal {
void speak() { [Link]("Dog barks"); }
}
Animal a = new Dog();
[Link](); // prints "Dog barks"
What is the difference between ArrayList and LinkedList in Java? When would you use one over the other?
Provide reasoning and basic example code.
ArrayList:
Insertion/removal at end is fast (O(1)), middle is slow (O(n)) due to shifting elements.
Good for scenarios where you need to access elements frequently by index.
LinkedList:
Insertion/removal at head/tail is fast (O(1)), middle insertion is O(n) if position must be found by index.
Example:
List<String> arrList = new ArrayList<>();
[Link]("A"); // O(1)
[Link](0); // O(1)
List<String> linkList = new LinkedList<>();
[Link]("A"); // O(1)
[Link]("B"); // O(1)
[Link](); // prints "Dog barks"
When to use:
Explain the difference between synchronized methods and synchronized blocks in Java. Why would you
use one over the other? Provide an example.
Synchronized Method:
When you declare a method as synchronized, only one thread can execute it at a time for a given
object (locks the object’s monitor).
Java
public synchronized void increment() {
counter++;
}
Equivalent to locking on this for instance methods.
Synchronized Block:
You can synchronize only a portion of code, and explicitly specify the object to lock.
Java
public void increment() {
synchronized(this) {
counter++;
}
}
or:
Java
synchronized(someOtherObject) {
// code
}
More flexible; can reduce time spent holding the lock, improving concurrency.
Synchronized block: When you don’t need to lock the whole method, just some code; or to lock on
a different object.
Next Question (Advanced: Exceptions): What is the difference between checked and unchecked
exceptions in Java? Give examples of each, and explain why we use checked exceptions.
Checked Exceptions:
Examples:
o IOException
o SQLException
o FileNotFoundException
Purpose: Enforce error handling for operations that may fail in normal circumstances (file IO, database
access).
Java
try {
FileReader f = new FileReader("[Link]"); // may throw
FileNotFoundException
} catch (FileNotFoundException e) {
[Link]();
}
Unchecked Exceptions:
Examples:
o NullPointerException
o ArrayIndexOutOfBoundsException
Enforces handling errors that are likely during normal program operations.
What are generics in Java? Why are they used, and how do they improve type safety? Provide a short
code example.
Generics:
Definition: Generics allow classes, interfaces, and methods to operate on a specified type (parameterized
types) without sacrificing type safety.
Why use:
o Type safety: Ensures only objects of the specified type can be added.
o No need for casting: Reduces runtime errors, makes code easier to read.
Code Example:
Java
List<Integer> list = new ArrayList<>(); // only Integers allowed
[Link](42);
// [Link]("hello"); // compile-time error
for (Integer i : list) {
[Link](i); // no cast needed
}
Without generics:
List list = new ArrayList();
[Link](42); // OK
[Link]("hello"); // OK
Streams in Java:
Example:
Java
List<Integer> numbers = [Link](1, 2, 3, 4, 5);
// Get squares of even numbers
List<Integer> squares = [Link]()
.filter(n -> n % 2 == 0) // filter even numbers
.map(n -> n * n) // map to squares
.collect([Link]()); // collect as List
Why answer like this? Interviewers want evidence you know how Java Streams work, their advantages, and basic
code usage.
Explain the difference between heap and stack memory in Java. What is stored where, and how does
garbage collection relate to this?
Stack Memory:
Used for method call frames, local variables, and primitive data.
Every time a method is called, a stack frame is created with its local variables and arguments.
Stack memory is smaller and managed by the JVM; grows/shrinks with method calls/returns.
Heap Memory:
Used for storing all objects (created via new) and arrays.
Variables in stack that reference objects actually point to their location in the heap.
Garbage Collection:
Automatic process in JVM that frees up heap memory by removing objects no longer referenced ("eligible for
GC").
Stack memory is managed automatically with method calls/returns; heap is managed with GC.
Example:
Java
try {
} catch (FileNotFoundException e) {
[Link]();
What is the Singleton pattern in Java? Why is it used, and how would you implement a thread-safe
Singleton? Give example code and reasoning.
Ensures only one instance of a class exists in the JVM, and provides a global point of access to that instance.
Useful for resource management (e.g., database connection pools, logging), where only one instance should
manage the resource.
Thread-Safe Implementation:
Java
public class Singleton {
private static Singleton instance;
private Singleton() { } // private constructor
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
}
Java
public class Singleton {
private static volatile Singleton instance;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized([Link]) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Or (Eager Initialization):
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance() { return instance; }
}
Explain the concept of Functional Interfaces in Java. How do they relate to lambdas? Give an example of
defining and using a custom functional interface.
Functional Interface:
An interface with exactly one abstract method (can have default/static methods).
@FunctionalInterface
interface MyFunc {
int operate(int a, int b);
}
// Using lambda expression:
MyFunc sum = (a, b) -> a + b;
[Link]([Link](5, 3)); // output: 8
Relation to Lambdas:
You can use a lambda expression anywhere a functional interface is expected, since Java knows which single
method to implement.
Common Examples:
What is Java Reflection? What are some use cases and limitations? Provide a code snippet that gets all
methods of a class at runtime.
Runnable:
Method:
Java
void run();
Does not return a value or throw checked exceptions.
Callable:
Method:
Java
V call() throws Exception;
Used with classes like ExecutorService, Future.
Example
Java
Callable<Integer> task = () -> {
return 42;
};
ExecutorService service = [Link]();
Future<Integer> future = [Link](task);
Integer result = [Link](); // result = 42
What is Java Reflection? What are some use cases and limitations? Provide a code snippet that gets all
methods of a class at runtime.
Java Reflection:
Allows programs to examine or modify the runtime properties (methods, fields, constructors, etc.) of classes.
Enables dynamic code, such as creating objects, invoking methods, or modifying fields, without knowing their
names at compile time.
Limitations:
Java
Class<?> clazz = [Link];
Method[] methods = [Link]();
for (Method m : methods) {
[Link]([Link]());
}
Explain what happens during Java class loading. What are the different class loaders, and why might you
use a custom class loader?
1. Loading: The class file is located and brought into memory by a class loader.
Types of ClassLoaders:
Bootstrap ClassLoader: Loads core Java classes ([Link]). Part of the JVM.
Extension (Platform) ClassLoader: Loads JDK extensions present in the ext directory.
Custom ClassLoader: User-defined for specialized loading (e.g., loading encrypted classes, plugins, or
classes from networks/databases).
Load classes in a special way (e.g., from encrypted files, over a network, or for class reloading in frameworks).
Example:
Java
ClassLoader cl = [Link]();
Class<?> clazz = [Link]("[Link]");
What are strong, weak, soft, and phantom references in Java? When would you use each?
1. Strong Reference:
2. Soft Reference:
o Usage: Caches that can be purged in memory shortage (e.g. image caches).
3. Weak Reference:
o Cleared as soon as the only references are weak (even if not low on memory).
4. Phantom Reference:
o Used to know exactly when an object is removed from memory (object is already finalized, used for
resource cleanup, and always enqueued post-GC).
Example:
Example:
Java
Object obj = new Object();
SoftReference<Object> softRef = new SoftReference<>(obj);
WeakReference<Object> weakRef = new WeakReference<>(obj);
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);
What is a memory leak in Java if there is garbage collection? Can you describe a scenario that causes a
leak, and how would you detect and prevent it?
A memory leak in Java occurs when objects that are no longer needed by the application remain in
memory because the garbage collector cannot remove them.
Memory Leak in Java:
Occurs when unused objects are still referenced, so they can't be garbage collected, causing memory usage to
grow.
Example Scenario:
Static collections:
Java
static List<User> userList = new ArrayList<>();
If you add user objects and never remove them, even if they’re obsolete, the list keeps growing—objects are never
eligible for GC.
Listener leaks: Registering event listeners but never deregistering them (e.g., GUI listeners).
Caches with strong references: E.g., HashMap caching objects but never removing them.
Detection:
Using tools like VisualVM, Eclipse MAT (Memory Analyzer Tool), YourKit, or JProfiler.
Look for steady memory increase, many unreachable objects referenced from roots (like static variables).
Prevention:
What is the difference between composition and inheritance in Java? In which scenarios would you prefer
one over the other, and why? Give examples.
Inheritance:
Example:
Java
class Animal { void speak() {} }
class Dog extends Animal { void speak() { [Link]("Bark"); } }
Here, Dog IS-A Animal.
Composition:
A class is composed of one or more objects from other classes; delegates behavior.
Example:
Java
class Engine { void start() {} }
class Car {
private Engine engine = new Engine(); // composition
void startCar() { [Link](); }
}
Here, Car HAS-A Engine.
When subclassing gives clear code re-use, follows Liskov Substitution, and matches real domain (“Dog IS-A
Animal”).
By default—especially for sharing code/behavior, or when combining functionality from different classes.
Serialization in Java
Definition: Serialization is the process of converting an object into a byte stream so it can be saved to a file,
sent over a network, etc.
Deserialization: The reverse process — converting a byte stream back into an object.
Use Case: Prevents sensitive or unnecessary data from being stored (e.g., passwords, temporary values).
Deadlock
In Java multithreading, a deadlock is a situation where two or more threads are permanently blocked because
each thread is waiting for a resource (lock) that another thread holds, and none of them can proceed.
2. Each thread acquires a lock on one resource and waits for another resource that is already locked by
another thread.
Method References ( : : )
Method references in Java provide a way to refer to methods or constructors directly by their names, making the code
more concise and readable. They are particularly useful for replacing simple lambda expressions that call existing
methods.
JVM (Java Virtual Machine): Runs compiled Java bytecode; platform-independent; manages memory and
execution.
JRE (Java Runtime Environment): JVM plus core libraries—enough to run Java applications.
JDK (Java Development Kit): JRE plus compilers, tools (javac etc)—used to develop Java programs.
Java
class Animal {}
class Dog extends Animal {}
Java
Animal a = new Dog(); [Link](); // Calls Dog's version
Java
private int age; public int getAge() { return age; }
Java
abstract class Shape { abstract void draw();
5. String Pool
Java
String str = "hello";
char[] arr = [Link]();
for(int i = 0, j = [Link]-1; i < j; i++, j--) {
char temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;
}
String reversed = new String(arr);
By extending Thread, you override the run() method; use if you need a new thread type.
By implementing Runnable, you share resources more easily and use thread pooling.
9. synchronized Keyword
Ensures only one thread executes a method/block at a time, preventing race conditions and data inconsistency.
Useful for simple flags; not as robust as synchronized for complex atomicity.
12. ConcurrentHashMap
Allows safe concurrent access with minimal locking by segmenting the map.
Intermediate: Transform stream (e.g. filter, map), lazy, don’t trigger processing.
Use abstract class for shared code; interface for common contract.
Java
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized([Link]) {
if(instance == null) instance = new Singleton();
}
}
return instance;
}
}
21. Deadlocks
Avoid deadlocks: Lock resources in consistent order, use timeouts, or avoid shared locks.
30. Reflection
Exceptions Quest
Examples:
Divide by zero
File not found
Null reference
Wrong input
Because these are exceptions that can be predicted and should be handled.
📌 Examples
IOException
SQLException
ClassNotFoundException
FileNotFoundException
📌 Definition
Exceptions that occur during runtime, and the compiler does NOT force you to handle them.
📌 Examples
ArithmeticException
NullPointerException
ArrayIndexOutOfBoundsException
Checked by
Type When occurs? Examples
compiler?
Checked
Yes Compile time IOException
Exception
Unchecked NullPointerExcepti
No Runtime
Exception on
Runtime
Error No OutOfMemoryError
(serious)
throw vs throws
throw
throws
Used in method signature to declare exceptions.
Unchecked
NullPointerException
ArithmeticException
ArrayIndexOutOfBoundsException
IllegalArgumentException
Checked
IOException
FileNotFoundException
SQLException
finally Block
📌 Purpose
exception occurs
no exception occurs
throw Keyword
📌 Purpose
📌 When used?
throws Keyword
📌 Purpose
“I am not handling the exception here, someone else should handle it.”
Method
Used inside Method body
signature
Number of
Only one at a time Multiple allowed
exceptions
"InvalidAgeException"
"InsufficientBalanceException"
"InvalidEmailFormatException"
What is try-with-resources?
It is a special form of try block that automatically closes resources after use.
✔ A resource means:
FileReader
BufferedReader
FileInputStream
Socket
Connection
PreparedStatement
Java
// use resource
// resource auto-closed
✔ No manual close()
✔ No resource leak
Eventually, if no one handles it, Java Runtime (JVM) handles it → program stops.
Exception Chaining?
Exception Chaining means one exception causes another exception, and Java allows you to link them.
📌 Why needed?
When a low-level method throws an exception, a higher-level method might want to throw a different, more
meaningful exception — without losing the original cause.
Consider:
Java
Answer:
Checked exceptions → Checked at compile-time (e.g., IOException).
Answer:
Yes, in rare cases:
1. [Link]()
2. JVM crash
3. Thread death
Answer:
If a method does not handle an exception, it is thrown to its caller.
Unchecked exceptions propagate automatically.
Checked exceptions must be declared using throws.
Answer:
Yes.
From Java 7 onward, you can also use multi-catch:
Java
catch(IOException | SQLException e)
✅ Q6. What happens when both try and finally have return statements?
Answer:
Return in finally overrides return in try.
Answer:
Linking one exception as the cause of another:
Java
Answer:
In try-with-resources, if both try block and close() throw exceptions,
Exception from close() becomes suppressed, not lost.
Answer:
Yes.
Constructors can throw checked or unchecked exceptions.
Rules:
✔ Can throw narrower checked exceptions
✔ Can throw any unchecked exception
❌ Cannot throw broader or new checked exceptions
Answer:
Unchecked exception → allowed, program fails at class loading.
Checked exception → NOT allowed (compile-time error).
Because:
Because:
No debugging information
Use try-with-resources:
Java
throw vs throws
Exception Propagation
Custom exceptions
finally behavior
Masked vs suppressed
Exception chaining
Collection Quest
Meaning:
Starts small
Expands automatically
ArrayList does not allocate memory until you add the first element.
Size = 1
Capacity = 10
That’s why:
ArrayList grows by 1.5x its old capacity. It allocates a new array using
newCapacity = oldCapacity + oldCapacity / 2,
then copies old elements to the new array, and the old array is garbage collected.
This resizing is costly, so adding is amortized O(1).
What is LinkedList?
List interface
Deque interface
So it supports:
FIFO (Queue)
LIFO (Stack)
List operations
class Node<E> {
E item;
Node<E> next;
Node<E> prev;
item → value
Because it must traverse from head or tail until it reaches the index.
No direct memory access.
No (like ArrayList)
value
next pointer
previous pointer
[Link] = [Link]();
[Link] = [Link]();
mismatches = output;
initGUI();
}
any way we need to work on “Adjust” creation
analyze the code and class and see what are the factor and thing responsible for this behavioure and see if it posibe to
create this new adjusted horizon above in please of down
give me code changes which are required to perform this task
How does the internal structure of HashMap change after Java 8, and why was this change made? What
problem does it solve?
Before Java 8, each HashMap bucket was a linked list of entries with the same hash code. If many keys collided (bad
hash distribution), these lists could become very long, making get/put operations O(n) for a bucket.
When a bucket becomes too large (default threshold: 8), it turns from a linked list into a balanced binary tree
(specifically, a red-black tree).
To fix performance issues caused by hash collisions and poor hashCode implementations.
Tree structure ensures consistent performance even with many collisions, preventing denial-of-service attacks
and speeding up operations on large bucket chains.
Summary:
Java 8 improved HashMap's worst-case performance by switching from linked lists to balanced trees within buckets
when collisions are high.
What is CopyOnWriteArrayList? How does it achieve thread safety, and when would you
use it over other collection types?
CopyOnWriteArrayList is a thread-safe variant of ArrayList from [Link].
It achieves thread safety by copying the entire array whenever it's modified (add, set, remove), so readers always see
a consistent snapshot. Its iterators are fail-safe—they iterate over the snapshot, so they never
throw ConcurrentModificationException.
When to use:
Ideal for situations where reads greatly outnumber writes (e.g., event listeners, configuration objects).
Not efficient for frequent modifications, since every write copies the array.
Use when you want thread-safe, lock-free reads with <i>rare</i> mutations.
Summary:
CopyOnWriteArrayList is best for read-heavy concurrency scenarios; it trades update performance for safe, fast reads
and fail-safe iteration.
Explain the difference between fail-fast and fail-safe iterators in Java. Give practical examples of each.
Fail-fast iterators detect structural modifications to the collection during iteration and immediately throw
a ConcurrentModificationException.
Example:
Java
To update safely during iteration, always use the iterator’s remove() method:
Java
Iterator<String> it = [Link]();
while ([Link]()) {
[Link]();
[Link](); // No exception
}
Fail-safe iterators allow concurrent modifications without exception because they iterate over a snapshot or copy of
the collection.
Examples include:
Modifications during iteration are visible only to future iterators—current iterator never fails.
Summary:
Fail-fast: throws error if modified during iteration (e.g., ArrayList, HashMap).
Fail-safe: allows safe iteration and concurrent updates (e.g., CopyOnWriteArrayList, ConcurrentHashMap).
What is the purpose of IdentityHashMap? How does it differ from HashMap in terms of key equality, and
when is it useful?
IdentityHashMap is a special Map implementation in Java where keys are compared using reference equality (==)
rather than object equality as in HashMap (which uses .equals() for comparison).
HashMap: Two keys are considered equal if their .equals() method returns true.
IdentityHashMap: Keys are only considered equal if they are the exact same object in memory (same
reference).
When is it useful?
IdentityHashMap is useful for scenarios where you need to distinguish keys based on their identity, not their contents—
such as object caches, tracking proxy objects, serialization frameworks, or mapping metadata to specific object
instances.
Example:
Java
[Link](new String("a"), "2"); // both entries remain, since keys are different objects