Core Java Interview Questions: Complete Guide with Answers and Examples

Hello! I am Ashutosh and I enjoy creating things that live on the internet. I was first introduced to programming in my freshman year and since then, I started developing Web projects.
I am currently working at Thoughtworks India as an Application Developer.
Mastering Core Java is essential for cracking technical interviews at top tech companies. Whether you’re preparing for coding rounds, design discussions, or scenario-based questions, having a solid grasp of Java fundamentals, memory management, multithreading, collections, and design patterns can set you apart.
This comprehensive guide covers all the essential Core Java interview questions in 2025, with clear explanations, comparisons, and code examples. From OOP principles to Java 8 features, JVM internals, and practical real-world scenarios, you’ll get a complete overview of the concepts that interviewers frequently test.
Use this guide to boost your Java knowledge, strengthen problem-solving skills, and confidently tackle interviews, making sure you’re well-prepared for both theoretical and hands-on coding rounds.
Object Oriented Programming Concepts
1. What are the principles of OOP?
OOP (Object-Oriented Programming) is based on four main principles:
Encapsulation – Bundling data and methods that operate on that data into a single unit (class).
Example: Private fields with public getters/setters.Abstraction – Hiding internal implementation details and exposing only essential features.
Example: Abstract classes and interfaces.Inheritance – Reusing properties and methods from an existing class into a new class.
Example:class Dog extends AnimalPolymorphism – The ability of objects to take multiple forms.
Example: Method overriding where the same method behaves differently in different subclasses.
These principles together make code modular, extensible, and maintainable.
2. Difference between abstraction and encapsulation
| Feature | Abstraction | Encapsulation |
| Purpose | Focuses on hiding implementation details | Focuses on bundling data and behavior |
| Achieved By | Abstract classes and interfaces | Access modifiers (private, public, etc.) |
| Concerned With | Design level | Implementation level |
| Example | Hiding database connection details behind an interface | Making class variables private and exposing getters/setters |
In short:
Abstraction hides what is done, Encapsulation hides how it’s done.
3. What is inheritance? How is it implemented in Java?
Inheritance allows one class to inherit properties and behaviors from another, promoting code reuse.
In Java:
class Parent {
void greet() { System.out.println("Hello!"); }
}
class Child extends Parent {
void greetChild() { System.out.println("Hi from Child!"); }
}
Here, Child inherits the greet() method from Parent.
Types of inheritance in Java:
Single
Multilevel
Hierarchical
Note: Java does not support multiple inheritance with classes to avoid ambiguity, but supports it with interfaces.
4. What is polymorphism? Types?
Polymorphism allows an object to behave differently based on context.
Types:
Compile-time polymorphism (Method Overloading):
Same method name, different parameter lists.
Resolved at compile-time.
void show(int a) {}
void show(String b) {}
Runtime polymorphism (Method Overriding):
Subclass provides a new implementation of a parent method.
Resolved at runtime using dynamic method dispatch.
Polymorphism improves flexibility and scalability in OOP systems.
5. What is method overloading vs overriding?
| Feature | Method Overloading | Method Overriding |
| When | Compile-time | Runtime |
| Class Relationship | Same class | Parent-child classes |
| Parameters | Must differ in type/number/order | Must be same |
| Return Type | Can differ | Must be same or covariant |
| Static Binding | Yes | No (uses dynamic binding) |
Example:
// Overloading
void add(int a, int b) {}
void add(double a, double b) {}
// Overriding
class A {
void show() {}
}
class B extends A {
void show() {}
}
6. Can we override static methods?
No.
Static methods are bound at compile-time (using class reference), not runtime (using object).
If a subclass defines a static method with the same name as the parent class’s static method, it hides the parent method — it’s not overriding.
class Parent {
static void greet() {}
}
class Child extends Parent {
static void greet() {}
} // Method hiding
7. Can a constructor be overridden?
No.
Constructors are not inherited, so overriding doesn’t apply.
However, constructors can be overloaded — a class can have multiple constructors with different parameter lists.
class Person {
Person() {}
Person(String name) {}
}
8. Why use interfaces instead of abstract classes?
Interfaces are preferred when you want to define a contract that multiple unrelated classes can implement.
Key reasons:
Java supports multiple interface inheritance, but not multiple class inheritance.
Promotes loose coupling — implementation can vary independently.
Ideal for defining APIs, services, or capabilities (e.g.,
Comparable,Runnable).
Example:
A class can implements Serializable, Comparable but can only extends one abstract class.
9. Interface vs Abstract Class
| Feature | Interface | Abstract Class |
| Inheritance | Multiple allowed | Single allowed |
| Contains | Abstract methods + constants (Java 8+: default & static methods too) | Can have abstract & concrete methods |
| Variables | public static final by default | Can be instance variables |
| Constructor | Not allowed | Allowed |
| Use Case | When defining behavior/contract | When defining base class with partial implementation |
In modern Java, interfaces are often used to define capabilities, while abstract classes define common base logic.
10. Can we create an object of abstract class or interface?
No, both cannot be instantiated directly.
They serve as blueprints for subclasses or implementing classes.
However, you can create:
- Anonymous inner classes or lambda expressions that provide concrete implementations.
Runnable r = new Runnable() {
public void run() { System.out.println("Running..."); }
};
Here, an anonymous implementation of the interface is created.
Java Basics
1. What is the Java Virtual Machine (JVM)?
The JVM (Java Virtual Machine) is an abstract machine that executes Java bytecode.
It provides a runtime environment for Java applications and is platform-dependent.
Key responsibilities:
Loading: Uses the ClassLoader to load class files.
Verifying: Ensures bytecode security.
Executing: Uses the Just-In-Time (JIT) compiler to convert bytecode to native code.
Memory Management: Allocates and manages heap, stack, and garbage collection.
In short:
👉 Java code → compiled to bytecode → executed by JVM → runs on any OS (platform independence).
2. Explain JRE vs JDK vs JVM.
| Component | Full Form | Purpose |
| JVM | Java Virtual Machine | Executes Java bytecode |
| JRE | Java Runtime Environment | Contains JVM + libraries required to run Java apps |
| JDK | Java Development Kit | Contains JRE + development tools (compiler, debugger, etc.) |
Relationship:
👉 JDK = JRE + development tools
👉 JRE = JVM + libraries
3. What is the role of main() method in Java?
main() is the entry point of any standalone Java application.
Signature:
public static void main(String[] args)
Breakdown:
public: Accessible by JVM.static: JVM can call it without creating an object.void: Doesn’t return any value.String[] args: Accepts command-line arguments.
Without main(), the program doesn’t have a starting point.
4. What happens if the main() method is not static?
If main() is not static, the JVM cannot invoke it directly because no object of the class exists yet.
This leads to a runtime error like:
Error: Main method is not static in class MainClass
JVM needs main() to be static so that it can call it without object instantiation.
5. Can Java run without main()?
In modern Java (Java 7+), no — every standalone program needs a main() method.
Earlier (in applets or servlet containers), Java classes could be run without main() because:
Applets start with the
init()method.Servlets are loaded and managed by a container (
init(),service(),destroy()).
For normal console applications → main() is mandatory.
Memory Management
1. Explain Java memory model.
The Java Memory Model (JMM) defines how Java threads interact through memory — how variables are read/written, and how visibility is ensured in concurrent execution.
It divides memory into:
Heap: Stores objects and their instance variables (shared across threads).
Stack: Each thread has its own stack storing method calls and local variables.
Method Area (Metaspace in Java 8+): Stores class-level metadata like method definitions and constant pool.
PC Register: Holds address of current executing instruction.
Native Method Stack: Used for native (non-Java) code execution.
The JMM ensures visibility, ordering, and atomicity across threads using keywords like volatile, synchronized, and final.
2. What is heap vs stack?
| Aspect | Heap | Stack |
| Stores | Objects, instance variables | Local variables, method calls |
| Shared? | Shared among all threads | Each thread has its own stack |
| Lifetime | Exists until object is garbage collected | Exists until method completes |
| Managed By | Garbage Collector | JVM automatically manages |
| Access Speed | Slower | Faster |
Example:
int x = 10; // stored in stack
Person p = new Person(); // object p in heap, reference in stack
3. What is PermGen and Metaspace?
PermGen (Permanent Generation):
Used before Java 8 to store class metadata, static variables, and interned strings.
Had a fixed size, which could causeOutOfMemoryError: PermGen space.Metaspace (Java 8+):
Replaced PermGen. It stores class metadata in native memory (not heap).
Grows dynamically as needed, reducing memory errors.
✅ In short: Metaspace is a more flexible, dynamic replacement for PermGen.
4. What is garbage collection? How does it work?
Garbage Collection (GC) is an automatic memory management process that reclaims memory from objects no longer reachable by any reference.
How it works:
JVM identifies unreachable objects (not referenced anywhere).
GC frees that memory space.
Memory is reused for new objects.
GC Algorithms:
Serial GC (single-threaded, small apps)
Parallel GC (multi-threaded)
G1 GC (Garbage First) – default in Java 9+, low pause time collector.
Phases:
Mark: Identify live objects.
Sweep/Compact: Remove dead objects and defragment memory.
Developers can trigger GC via System.gc(), but JVM decides the actual execution time.
5. Finalize method – how and when is it called?
finalize() is a method defined in the Object class:
protected void finalize() throws Throwable
It’s called by the Garbage Collector before reclaiming an object’s memory — a last chance to release resources.
However:
Execution is not guaranteed or timely.
It might never be called if the program exits before GC runs.
✅ Since Java 9, finalize() is deprecated.
Modern alternatives:
Use
try-with-resourcesfor closing streams.Implement
AutoCloseablefor cleanup logic.
Access Modifiers
1. Difference between private, protected, public, and default
Java provides four access levels to control visibility of classes, methods, and variables.
| Modifier | Within Class | Within Package | Subclass (Other Package) | Outside Package |
| private | ✅ | ❌ | ❌ | ❌ |
| default (no modifier) | ✅ | ✅ | ❌ | ❌ |
| protected | ✅ | ✅ | ✅ | ❌ |
| public | ✅ | ✅ | ✅ | ✅ |
Summary:
private → Most restrictive; used for encapsulation.
default → Accessible within the same package.
protected → Visible to subclasses even if they’re in different packages.
public → Accessible from anywhere.
Example:
public class Person {
private int age;
protected String name;
public void greet() {}
}
2. Can a class be private in Java?
Top-level (outer) classes cannot be private — they must be either public or default.
However, inner classes can be private.
Example:
class Outer {
private class Inner { // ✅ allowed
void show() { System.out.println("Inner"); }
}
}
If a top-level class were private, no other class (even in the same package) could access it — defeating the purpose of reusability.
3. What are static blocks?
A static block in Java is used for class-level initialization.
It runs once, when the class is first loaded into memory (before any constructor or object creation).
Example:
class DatabaseConnection {
static {
System.out.println("Initializing DB connection...");
}
}
Use cases:
Initialize static variables.
Load configurations.
Perform one-time setup (e.g., registering JDBC drivers).
Order of execution:
Static variables.
Static blocks (in order of appearance).
Constructors (when object is created).
Exception Handling
1. Checked vs Unchecked Exceptions?
| Type | Checked Exception | Unchecked Exception |
| Inheritance | Subclass of Exception (excluding RuntimeException) | Subclass of RuntimeException |
| Checked at | Compile-time | Runtime |
| Handling Required? | Must be handled or declared using throws | Optional |
| Examples | IOException, SQLException, FileNotFoundException | NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException |
Key point:
Checked exceptions represent recoverable errors, while unchecked ones indicate programming bugs (e.g., null access).
2. Difference between throw and throws?
| Keyword | throw | throws |
| Purpose | Used to actually throw an exception | Declares that a method may throw exceptions |
| Usage Place | Inside method body | In method signature |
| Follows | Single exception instance | One or more exception classes |
| Example | throw new IOException("File not found"); | void readFile() throws IOException {} |
Example:
void readFile() throws IOException {
throw new IOException("Error reading file");
}
3. Can we have try block without catch/finally?
No ❌
A try block must be followed by at least one of the following:
A
catchblockA
finallyblock
However, try-finally without catch is valid:
try {
System.out.println("Try block");
} finally {
System.out.println("Cleanup code");
}
This ensures cleanup executes even if no exception occurs.
4. What is the use of finally block?
The finally block is used for resource cleanup — it executes always, regardless of whether an exception occurs or not.
Example:
try {
FileInputStream fis = new FileInputStream("data.txt");
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Closing resources...");
}
✅ Executed:
After try or catch block
Even if
returnis used inside try or catch
❌ Not executed if JVM exits viaSystem.exit(0)or power failure.
Modern alternative:
Use try-with-resources (Java 7+) to auto-close resources.
5. Custom exception in Java?
A custom exception allows developers to define domain-specific error types.
Steps to create:
Extend
Exception(for checked) orRuntimeException(for unchecked).Add constructors for custom messages.
Example:
class InvalidAgeException extends Exception {
public InvalidAgeException(String msg) {
super(msg);
}
}
class Validator {
void validate(int age) throws InvalidAgeException {
if (age < 18)
throw new InvalidAgeException("Age must be >= 18");
}
}
Use cases:
Validation (e.g., invalid user input)
Business logic constraints
Domain-specific error reporting (e.g.,
InsufficientBalanceException)
Collections Framework
1. List vs Set vs Map?
| Feature | List | Set | Map |
| Stores | Ordered collection of elements | Unique elements (no duplicates) | Key-value pairs |
| Duplicates | Allowed | Not allowed | Keys: not allowed, Values: allowed |
| Order | Maintains insertion order | Depends on implementation | Depends on implementation |
| Implementations | ArrayList, LinkedList, Vector | HashSet, LinkedHashSet, TreeSet | HashMap, TreeMap, LinkedHashMap |
Example:
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<Integer, String> map = new HashMap<>();
2. ArrayList vs LinkedList?
| Aspect | ArrayList | LinkedList |
| Data Structure | Dynamic array | Doubly linked list |
| Access Time | O(1) for index-based access | O(n) traversal required |
| Insertion/Deletion (middle) | O(n) | O(1) if node reference known |
| Memory Usage | Less (compact) | More (extra node references) |
| Use Case | Random access | Frequent insertions/deletions |
Example:
Use
ArrayListwhen reads are frequent.Use
LinkedListwhen insertions/removals are frequent.
3. HashMap vs Hashtable?
| Feature | HashMap | Hashtable |
| Thread-Safety | Not synchronized | Synchronized |
| Null Keys/Values | Allows one null key, multiple null values | Doesn’t allow nulls |
| Performance | Faster (no locking) | Slower (locks entire table) |
| Introduced In | Java 1.2 | Java 1.0 |
| Preferred? | Yes, in modern Java | Legacy class |
✅ For thread-safe alternatives, use ConcurrentHashMap instead of Hashtable.
4. How does HashMap work internally?
HashMap stores data in buckets using a hashing mechanism.
Process:
Key’s
hashCode()is computed.The hash is mapped to an index in the bucket array (
(n - 1) & hash).Each bucket holds a linked list or tree (Java 8+).
On
put():If key exists → value replaced.
If not → new node added.
On
get():- Hash computed → bucket located → key compared using
equals().
- Hash computed → bucket located → key compared using
Optimization (Java 8+):
- If bucket size > 8, converts linked list → balanced tree (Red-Black Tree) for O(log n) lookup.
5. What is the load factor and threshold in HashMap?
Load Factor: Defines how full the HashMap can get before resizing (default = 0.75).
Threshold:
capacity × loadFactor.
When the number of entries exceeds this threshold, HashMap resizes (doubles its capacity).
Example:
HashMap<String, Integer> map = new HashMap<>(16, 0.75f);
✅ Resizing improves performance but comes with a cost — it’s best to initialize maps with an estimated size to minimize rehashing.
6. What are fail-fast and fail-safe iterators?
| Type | Behavior | Example Collections |
| Fail-Fast | Throws ConcurrentModificationException if the collection is modified while iterating | ArrayList, HashMap |
| Fail-Safe | Works on a clone or snapshot of the collection | ConcurrentHashMap, CopyOnWriteArrayList |
Example:
for (Integer i : list) {
list.add(10); // ❌ throws ConcurrentModificationException
}
✅ Use fail-safe collections in concurrent environments.
7. What is ConcurrentHashMap and how is it different?
ConcurrentHashMap is a thread-safe alternative to HashMap that provides high concurrency with minimal locking.
How it differs:
No full-table lock (uses segment-level locking or CAS in Java 8+).
Null keys/values are not allowed.
Iterators are fail-safe (operate on snapshot).
Performs better than
Hashtableunder multithreading.
Example:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);
8. TreeMap vs HashMap?
| Feature | HashMap | TreeMap |
| Order | No ordering | Sorted (natural/comparator) |
| Implementation | Hash table | Red-Black tree |
| Null Keys | Allows one | Doesn’t allow null key |
| Performance | O(1) average | O(log n) |
| Use Case | Fast lookups | Sorted data retrieval |
Example:
Map<Integer, String> map = new TreeMap<>();
map.put(2, "B");
map.put(1, "A"); // Automatically sorted by key
9. What is LinkedHashMap?
LinkedHashMap maintains insertion order or access order of entries.
Internally:
It extends HashMap and adds a doubly-linked list to preserve order.
Example:
Map<Integer, String> map = new LinkedHashMap<>();
map.put(1, "A");
map.put(2, "B");
✅ Useful when you need predictable iteration order or LRU caching (using removeEldestEntry).
10. When to use ArrayList vs Vector?
| Feature | ArrayList | Vector |
| Synchronization | Not synchronized | Synchronized |
| Performance | Faster | Slower (locks every method) |
| Introduced In | Java 1.2 | Java 1.0 (legacy) |
| Growth | Grows by 50% | Grows by 100% (doubles) |
✅ Modern Java avoids Vector.
Use ArrayList for single-threaded cases, or Collections.synchronizedList() if synchronization is needed.
Multithreading and Concurrency
1. Difference between process and thread?
| Feature | Process | Thread |
| Definition | Independent program in execution | Smallest unit of a process |
| Memory | Has its own memory space | Shares memory with other threads of same process |
| Communication | Inter-process communication is complex | Easier via shared objects |
| Failure Impact | One process crash doesn’t affect others | Thread crash may affect whole process |
| Example | Running two Java programs | Two threads in same Java program |
In short: Threads share the same heap, enabling lightweight multitasking within a single process.
2. Ways to create a thread in Java?
There are three main ways:
Extend
Threadclassclass MyThread extends Thread { public void run() { System.out.println("Thread running..."); } } new MyThread().start();Implement
Runnableinterfaceclass MyTask implements Runnable { public void run() { System.out.println("Running via Runnable"); } } new Thread(new MyTask()).start();Use
ExecutorServiceorCallable(preferred in modern Java)ExecutorService service = Executors.newFixedThreadPool(2); service.submit(() -> System.out.println("Running in pool"));
✅ Best practice: Use ExecutorService to manage threads efficiently.
3. Thread vs Runnable?
| Feature | Thread | Runnable |
| Inheritance | Requires extending Thread | Can be implemented along with other interfaces |
| Code Reuse | Less flexible | More flexible (no multiple inheritance issue) |
| Preferred | For small/simple use | Runnable preferred for real-world apps |
Example:
If your class already extends another class, use Runnable since Java doesn’t support multiple inheritance.
4. What is thread lifecycle?
A thread in Java passes through these five states:
New – Created but not started (
new Thread()).Runnable – Ready to run, waiting for CPU (
start()called).Running – Currently executing.
Blocked/Waiting – Waiting for a resource or another thread.
Terminated – Execution completed or stopped.
Example:
Thread t = new Thread(() -> {});
t.start(); // Runnable
5. Difference between wait, sleep, join?
| Method | Defined In | Releases Lock? | Purpose |
| wait() | Object class | ✅ Yes | Waits until notified (notify() / notifyAll()) |
| sleep() | Thread class | ❌ No | Pauses execution for given time |
| join() | Thread class | ❌ No | Waits for another thread to finish |
Example:
Thread t = new Thread(() -> System.out.println("Task"));
t.start();
t.join(); // waits for t to finish
6. What is synchronized block/method?
The synchronized keyword ensures mutual exclusion — only one thread can access a block/method at a time for a given object.
Types:
Synchronized method
synchronized void increment() { count++; }Synchronized block
void increment() { synchronized(this) { count++; } }
Benefits: Prevents race conditions.
Downside: Can reduce performance due to locking.
7. What is a deadlock? How to prevent it?
A deadlock occurs when two or more threads are waiting for each other’s locks indefinitely.
Example:
synchronized (obj1) {
synchronized (obj2) { ... }
}
Another thread might lock obj2 first, then wait for obj1.
Prevention:
Acquire locks in a consistent order.
Use
tryLock()with timeout (ReentrantLock).Avoid nested locks where possible.
8. What is volatile keyword?
The volatile keyword ensures that a variable’s value is always read from main memory, not from a thread’s local cache.
Example:
volatile boolean flag = true;
If one thread changes flag, other threads immediately see the updated value.
Important:
Ensures visibility, not atomicity.
For compound operations (e.g.,
count++), use synchronization orAtomicInteger.
9. Difference between ExecutorService and Thread?
| Aspect | Thread | ExecutorService |
| Creation | Manually create and start threads | Manages thread pool automatically |
| Reusability | One-time use | Threads are reused |
| Performance | Higher overhead | More efficient for multiple tasks |
| Introduced | Java 1.0 | Java 5 (java.util.concurrent) |
Example:
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(() -> System.out.println("Task executed"));
executor.shutdown();
✅ Best practice: Always use ExecutorService for managing multiple threads efficiently.
10. What is thread safety?
Thread safety means an object or code segment behaves correctly when accessed by multiple threads simultaneously.
Ways to achieve:
Use immutable objects
Use synchronized blocks
Use atomic classes (
AtomicInteger,AtomicReference)Use concurrent collections (
ConcurrentHashMap,CopyOnWriteArrayList)
Example:
AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();
✅ Thread-safe code avoids race conditions and data inconsistency.
Java 8 Features
1. What are the major features introduced in Java 8?
Java 8 introduced functional programming concepts and several performance improvements.
Key Features:
Lambda Expressions
Functional Interfaces
Stream API
Optional class
Method References
Default and Static methods in Interfaces
Date and Time API (
java.time)Parallel Streams
2. What are lambda expressions?
A lambda expression provides a concise way to represent anonymous functions.
Syntax:
(parameter) -> expression
Example:
List<String> names = Arrays.asList("John", "Jane", "Max");
names.forEach(name -> System.out.println(name));
Before Java 8:
for (String name : names)
System.out.println(name);
✅ Advantages:
Reduces boilerplate code
Enables functional programming
Works well with Streams and Collections
3. What is a functional interface?
A functional interface is an interface that contains exactly one abstract method.
It can have default or static methods as well.
Example:
@FunctionalInterface
interface Calculator {
int add(int a, int b);
}
Built-in Functional Interfaces (in java.util.function):
Predicate<T>→ returns booleanFunction<T, R>→ transforms T to RConsumer<T>→ accepts and performs actionSupplier<T>→ returns value without input
Example:
Predicate<Integer> isEven = x -> x % 2 == 0;
System.out.println(isEven.test(4)); // true
4. What is the Stream API?
The Stream API is used to process collections of data in a declarative and functional style.
Example:
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squares = nums.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println(squares);
Key Operations:
Intermediate →
filter(),map(),sorted()Terminal →
collect(),forEach(),count(),reduce()
✅ Streams don’t modify the original collection.
5. What is the difference between map() and flatMap()?
| Method | Purpose | Example |
| map() | Transforms each element | [1,2,3] → [1,4,9] |
| flatMap() | Flattens nested streams | [[1,2],[3,4]] → [1,2,3,4] |
Example:
List<List<Integer>> list = Arrays.asList(Arrays.asList(1,2), Arrays.asList(3,4));
list.stream().flatMap(Collection::stream).forEach(System.out::println);
6. What is the Optional class?
Optional<T> is a container that may or may not hold a non-null value.
It helps avoid NullPointerException.
Example:
Optional<String> name = Optional.ofNullable(getName());
System.out.println(name.orElse("Unknown"));
Common methods:
isPresent()orElse()orElseGet()orElseThrow()map()andflatMap()
✅ Always use Optional for return types, not fields.
7. What are method references?
Method references provide a shorthand for calling existing methods using ::.
Example:
list.forEach(System.out::println);
Types:
Static method →
ClassName::staticMethodInstance method →
object::instanceMethodConstructor →
ClassName::new
Example:
Supplier<List<String>> supplier = ArrayList::new;
8. What are default and static methods in interfaces?
Default methods: Provide a method body inside an interface.
Example:
interface Vehicle {
default void start() {
System.out.println("Vehicle started");
}
}
Static methods in interfaces belong to the interface itself:
interface Utils {
static void show() {
System.out.println("Static method in interface");
}
}
✅ These features were introduced to maintain backward compatibility when new methods were added to interfaces like List and Map.
9. What is the new Date and Time API (java.time)?
Java 8 introduced a modern, immutable, thread-safe Date-Time API.
Key Classes:
LocalDate,LocalTime,LocalDateTimeZonedDateTimePeriod,DurationDateTimeFormatter
Example:
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);
System.out.println(tomorrow);
✅ No more java.util.Date and SimpleDateFormat pain!
10. What are parallel streams?
Parallel streams allow data to be processed in multiple threads automatically.
Example:
list.parallelStream()
.filter(x -> x > 10)
.forEach(System.out::println);
Note:
Use parallel streams for CPU-intensive operations.
Avoid for IO-bound or small datasets (due to overhead).
Strings
1. String vs StringBuilder vs StringBuffer?
| Feature | String | StringBuilder | StringBuffer |
| Mutability | Immutable | Mutable | Mutable |
| Thread-safety | Not thread-safe | Not thread-safe | Thread-safe (synchronized) |
| Performance | Slower (creates new objects) | Faster (no synchronization) | Slightly slower (synchronization overhead) |
| Use Case | When data doesn’t change | Single-threaded string manipulations | Multi-threaded string manipulations |
Example:
String s = "Hello";
s.concat(" World"); // New object created
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // Modified in place
✅ For most use cases → prefer StringBuilder (fast, flexible).
2. How are strings stored in memory?
Strings are stored in a special area of heap memory called the String Constant Pool (SCP).
When you create a string literal, e.g.,
"Java", it’s interned — meaning:If
"Java"already exists in the pool, the same reference is reused.If not, it’s added to the pool.
Example:
String s1 = "Java";
String s2 = "Java";
System.out.println(s1 == s2); // true (same reference)
✅ String literals are interned;new String("Java") creates a new object on the heap (not in SCP).
3. What is the String Constant Pool?
The String Constant Pool (SCP) is part of the heap memory (since Java 7+).
It’s a cache that stores unique string literals to improve performance and save memory.
Example:
String a = "Test";
String b = "Test";
System.out.println(a == b); // true (both refer to same object)
If created using new:
String c = new String("Test");
System.out.println(a == c); // false (different objects)
✅ You can manually add strings to the pool using intern():
String d = c.intern();
System.out.println(a == d); // true
4. Why are Strings immutable in Java?
Reasons:
Security: Used in sensitive contexts (ClassLoader, File paths, URLs).
Thread-safety: Immutable objects can be shared safely between threads.
Caching: Hash code of a string is cached; immutability ensures it’s consistent.
String Pool Optimization: Same string literals can be reused safely.
Example:
String s = "Java";
s.concat(" Rocks"); // creates a new string
✅ Once created, the value of a String object cannot be changed.
5. How does equals() work in String?
The equals() method compares the contents (values) of two strings,
while the == operator compares references.
Example:
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2); // false (different objects)
System.out.println(s1.equals(s2)); // true (same content)
✅ String overrides equals() and hashCode() from Object class to compare actual text.
6. How does hashCode() work in Strings?
The hash code for a string is computed based on its characters:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]Because strings are immutable, their hash code is cached for performance.
✅ Used extensively in collections like HashMap and HashSet.
7. How do substring(), split(), and join() work?
substring(begin, end)
Returns part of the string.
Creates a new String (does not modify original).
Example:
String s = "developer";
System.out.println(s.substring(0, 3)); // "dev"
split(regex)
- Splits a string into an array based on a delimiter.
String s = "a,b,c";
String[] arr = s.split(",");
String.join(delimiter, elements...)
String result = String.join("-", "Java", "Python", "C++");
System.out.println(result); // "Java-Python-C++"
8. What is String interning?
Interning ensures that identical strings share the same reference in the String Pool.
Example:
String s1 = new String("Java");
String s2 = s1.intern();
String s3 = "Java";
System.out.println(s2 == s3); // true
✅ Improves memory efficiency, especially when there are many repeated strings.
9. What are common StringBuilder methods?
append()– concatenates datainsert()– inserts at positiondelete()– removes substringreverse()– reverses contentcapacity()– returns current buffer capacity
Example:
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World").reverse();
System.out.println(sb); // "dlroW olleH"
10. Can we make String mutable in Java?
Not directly.
However, you can simulate mutability using:
StringBuilderorStringBufferReflection (not recommended)
Creating a wrapper class with a mutable reference internally
Java Keywords and Modifiers
1. Difference between final, finally, and finalize?
| Keyword | Purpose | Example |
| final | Restricts modification | final int x = 10; or final class MyClass |
| finally | Block to execute after try/catch | try {…} finally {…} |
| finalize() | Called by GC before object is destroyed | protected void finalize() {…} |
Summary:
final→ compile-time constant, prevents inheritance/overridingfinally→ runtime block for cleanupfinalize()→ deprecated method, used for cleanup before garbage collection
2. What does static mean?
Static members belong to the class, not instances.
Static variable: Shared across all objects
Static method: Can be called without an object
Static block: Executes once at class loading
Example:
class Demo {
static int count;
static { System.out.println("Class loaded"); }
static void show() { System.out.println("Static method"); }
}
Demo.show();
System.out.println(Demo.count);
✅ Use static for memory efficiency and shared state.
3. What is transient?
Transient is a keyword used in serialization.
Fields marked as transient are not serialized.
Example:
class User implements Serializable {
private String name;
private transient String password; // won’t be saved
}
✅ Useful for sensitive data like passwords or temporary fields.
4. What is volatile?
Ensures visibility of changes across threads.
Guarantees that reads/writes go directly to main memory.
Does not guarantee atomicity.
Example:
volatile boolean running = true;
while (running) {
/* do work */
}
Without volatile, one thread may never see the updated value.
5. Difference between this and super?
| Keyword | Purpose | Example |
| this | Refers to current object | this.name = name; |
| super | Refers to parent class | super.toString(); |
this()→ calls current class constructorsuper()→ calls parent class constructorBoth must be the first statement in constructor when used
6. Additional Notes on Keywords/Modifiers
abstract: Cannot instantiate class, may contain abstract methods
synchronized: Ensures mutual exclusion for threads
native: Method implemented in platform-specific code (C/C++)
strictfp: Ensures floating-point calculations are platform-independent
default (in interfaces): Provides default method implementation
var (Java 10+): Type inference for local variables
Java Inner Classes
1. What are inner classes?
An inner class is a class defined within another class.
They allow logical grouping of classes and access to private members of the outer class.
Types of inner classes:
Member (non-static) inner class
Static nested class
Local inner class
Anonymous inner class
2. What are static nested classes?
A static nested class is declared with the
statickeyword.Unlike member inner classes, it does not have access to instance variables of the outer class.
Can be instantiated without an object of the outer class.
Example:
class Outer {
static class Nested {
void show() { System.out.println("Static nested class"); }
}
}
Outer.Nested nested = new Outer.Nested();
nested.show();
✅ Useful for grouping classes logically and reducing namespace pollution.
3. Difference between local, anonymous, and member classes
| Type | Definition | Scope | Example |
| Member inner class | Defined at class level (non-static) | Can access outer class members | class Outer { class Inner {} } |
| Static nested class | Defined with static keyword | Only static members of outer class | Outer.Nested nested = new Outer.Nested(); |
| Local inner class | Defined inside a method | Only visible within method | void method() { class Local {} } |
| Anonymous inner class | No class name, used for instant implementation | Usually for implementing interfaces or extending classes | Runnable r = new Runnable() { public void run() {} }; |
Key points:
Member inner classes hold a reference to outer class.
Static nested classes don’t hold outer class reference, so memory footprint is smaller.
Anonymous classes are great for event handlers and callbacks.
Example of anonymous inner class:
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Anonymous Runnable");
}
};
new Thread(r).start();
4. When to use inner classes?
When a class is only relevant to its outer class.
For callbacks, listeners, or adapters.
To encapsulate helper classes without exposing them publicly.
To access outer class private members without getters/setters.
✅ Correct use of inner classes improves code readability, encapsulation, and design.
Design Principles / Patterns
1. What is SOLID?
SOLID is an acronym for five design principles that make code more maintainable, scalable, and testable:
| Principle | Description |
| S – Single Responsibility Principle (SRP) | A class should have only one reason to change. Each class should focus on a single functionality. |
| O – Open/Closed Principle (OCP) | Classes should be open for extension, closed for modification. |
| L – Liskov Substitution Principle (LSP) | Subclasses should be substitutable for their parent classes without affecting program correctness. |
| I – Interface Segregation Principle (ISP) | Clients should not be forced to depend on methods they don’t use. Prefer multiple small interfaces over one large interface. |
| D – Dependency Inversion Principle (DIP) | High-level modules should not depend on low-level modules. Both should depend on abstractions. |
✅ These principles are key to writing clean and scalable Java applications.
2. What is the Singleton pattern?
The Singleton pattern ensures a class has only one instance and provides a global access point.
Implementation (Thread-safe, lazy initialization):
class Singleton {
private static volatile Singleton instance;
private Singleton() {} // private constructor
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
✅ Use cases:
Logger
Configuration manager
Thread pool manager
3. How to implement an immutable class?
Steps to make a class immutable:
Declare class as
final.Make all fields
privateandfinal.No setters.
Return deep copies of mutable objects.
Example:
final class Employee {
private final String name;
private final int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
✅ Immutable objects are thread-safe and prevent unintended state changes.
4. What is the Factory pattern?
The Factory pattern provides a way to create objects without exposing instantiation logic.
Example:
interface Shape { void draw(); }
class Circle implements Shape {
public void draw() { System.out.println("Circle"); }
}
class Square implements Shape {
public void draw() { System.out.println("Square"); }
}
class ShapeFactory {
public static Shape getShape(String type) {
if (type.equalsIgnoreCase("circle")) return new Circle();
if (type.equalsIgnoreCase("square")) return new Square();
throw new IllegalArgumentException("Unknown shape");
}
}
// Usage
Shape s = ShapeFactory.getShape("circle");
s.draw();
✅ Use when object creation logic is complex or depends on conditions.
5. What is Dependency Injection (DI)?
Dependency Injection is a design pattern where an object receives its dependencies from external sources rather than creating them internally.
Types of DI:
Constructor injection – dependencies passed via constructor
Setter injection – dependencies set via setters
Interface injection – using an interface to inject dependencies (less common)
Example (Constructor DI):
class Service {
private final Repository repo;
public Service(Repository repo) { this.repo = repo; }
}
Repository repo = new Repository();
Service service = new Service(repo);
✅ Benefits:
Promotes loose coupling
Easier unit testing
Improves maintainability
JVM Internals and Performance
1. What happens when you run a Java program?
Steps in Java program execution:
Compilation:
.javasource code is compiled into.classbytecode usingjavac.Class loading: JVM loads the
.classfiles into memory using ClassLoaders.Bytecode verification: Ensures code is valid and doesn’t violate JVM constraints.
Execution: Just-In-Time (JIT) compiler converts bytecode into native machine code for performance.
Memory allocation: Objects are created in the heap; references stored in stack.
Garbage Collection: Unreferenced objects are cleaned automatically.
✅ Key point: JVM allows platform independence by abstracting underlying OS and hardware.
2. Explain class loading process
Class loading is handled by the JVM in three phases:
Loading: Loads
.classfile into memory using ClassLoader.Linking:
Verification: Ensures bytecode integrity
Preparation: Allocates memory for static variables
Resolution: Resolves symbolic references
Initialization: Executes static blocks and initializes static fields.
3. What is the role of ClassLoader?
ClassLoader loads Java classes into JVM at runtime.
Types of ClassLoaders:
Bootstrap ClassLoader: Loads core Java classes (rt.jar)
Extension ClassLoader: Loads JDK extension libraries (
lib/ext)Application ClassLoader: Loads classes from classpath (your code)
Custom ClassLoader: Can be created for dynamic class loading
✅ ClassLoader ensures lazy loading — classes are loaded only when needed.
4. How does Java achieve platform independence?
Java code is compiled into bytecode (
.classfile), not native machine code.JVM interprets bytecode or uses JIT to convert to native code.
Same bytecode can run on any platform with a compatible JVM.
Key principle: Write Once, Run Anywhere (WORA).
5. How to improve Java performance?
Memory management:
Use proper data structures (ArrayList vs LinkedList)
Minimize object creation, reuse objects
Multithreading: Use ExecutorService, parallel streams wisely
Collections: Use Concurrent collections for thread safety
Garbage Collection tuning: Adjust heap size and GC algorithm
String handling: Use StringBuilder instead of String concatenation in loops
Profiling: Use tools like VisualVM, JConsole to detect bottlenecks
6. Garbage Collection overview
Automatic memory management by JVM
Removes unreachable objects from heap
Common collectors: Serial, Parallel, CMS, G1
GC events: Minor GC (young generation), Major GC (old generation)
Finalize() is called before GC (deprecated in Java 9+)
✅ Modern JVM uses generational GC for efficiency.
7. Heap vs Stack
| Memory Area | Purpose | Example |
| Heap | Stores objects and arrays | new Employee() |
| Stack | Stores method call frames, local variables | int x = 10; |
Stack memory is LIFO, automatically cleaned.
Heap memory is shared, cleaned by GC.
8. PermGen vs Metaspace
PermGen (Java 7 and below): Stores class metadata; fixed size → risk of
OutOfMemoryError.Metaspace (Java 8+): Dynamically resizable; stored in native memory → reduces class loading errors.
Miscellaneous Java Concepts
1. Serialization vs Deserialization
Serialization: Converts a Java object into a byte stream to save to disk or send over a network.
Deserialization: Converts the byte stream back into a Java object.
Example:
// Serialization
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.obj"));
oos.writeObject(employee);
// Deserialization
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.obj"));
Employee e = (Employee) ois.readObject();
Notes:
Use
transientkeyword for fields that shouldn’t be serialized.Serializable classes must implement
Serializable.
2. What is a marker interface?
An interface without methods used to mark a class with special behavior.
Examples:
Serializable,Cloneable,Remote.
Purpose: Provides metadata to JVM or frameworks.
3. What is instanceof keyword?
- Checks if an object is an instance of a specific class or implements an interface.
Example:
String s = "Java";
if (s instanceof String) {
System.out.println("s is a String");
}
✅ Always returns true for null checks: null instanceof String → false.
4. What is reflection API?
Reflection allows inspecting and manipulating classes, methods, and fields at runtime.
Can be used to:
Get class info (
Class<?> clazz = obj.getClass();)Access private fields/methods
Dynamically create instances
Example:
Class<?> clazz = Class.forName("java.util.ArrayList");
Object obj = clazz.getDeclaredConstructor().newInstance();
✅ Useful for frameworks like Spring, Hibernate, and testing tools.
5. What is autoboxing and unboxing?
Autoboxing: Automatic conversion from primitive to wrapper class
int x = 10; Integer y = x; // autoboxingUnboxing: Wrapper class → primitive
Integer a = 20; int b = a; // unboxing
6. What is enum in Java?
enumis a special class representing a fixed set of constants.Can have fields, methods, and constructors.
Example:
enum Day { MONDAY, TUESDAY, WEDNESDAY }
Day today = Day.MONDAY;
✅ Useful for type safety instead of string constants.
7. Can we override private methods?
No, private methods are not visible to subclasses.
They are class-specific and cannot be overridden, but they can be redeclared in a subclass.
8. Can we overload main method?
- Yes, you can overload
main:
public static void main(String[] args) { }
public static void main(int[] args) { }
- JVM always calls the String[] main method.
9. Can constructor be private?
Yes, used in Singleton pattern or factory methods.
Prevents direct instantiation from outside the class.
10. What are annotations in Java?
Metadata for classes, methods, fields.
Examples:
@Override,@Deprecated,@FunctionalInterfaceCustom annotation example:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Test {
}
11. What is JavaBeans?
JavaBean: A reusable class following:
Private fields
Public getters and setters
No-arg constructor
Serializable
✅ Used for encapsulation and frameworks like JSP, JSF, and Spring.
12. What is var keyword in Java?
- Introduced in Java 10 for local variable type inference.
var name = "Ashutosh"; // inferred as String
- Cannot be used for method parameters, fields, or return type.
13. What are records in Java?
Introduced in Java 14 as immutable data carriers.
Automatically generate constructor, getters, equals, hashCode, toString.
record Employee(String name, int age) { }
Employee e = new Employee("John", 25);
✅ Great for DTOs and value objects.
Learn more about records here.
14. Difference between compile-time and runtime errors
| Type | When occurs | Example |
| Compile-time error | During compilation | Syntax error, missing semicolon |
| Runtime error | During program execution | NullPointerException, ArrayIndexOutOfBounds |
Real-World Scenario-Based Questions
1. How would you optimize a large collection for search?
Scenario: You have a large dataset and need frequent lookups.
Approach:
Choose the right data structure:
HashMapfor O(1) key-value lookup.TreeMapif sorted order is required (O(log n) lookup).HashSetfor unique element search.
Indexing: Precompute indices for frequent queries.
Use streams with parallel processing if data is very large.
Avoid unnecessary object creation: Use primitives or immutable objects.
Memory considerations: If memory is tight, consider using compressed data structures or disk-based solutions.
Example:
Map<String, Employee> employeeMap = new HashMap<>();
for(Employee e: employees) {
employeeMap.put(e.getId(), e);
}
// Lookup by ID is now O(1)
2. How to handle concurrency in a shared resource?
Scenario: Multiple threads need to access/update shared data.
Approach:
Synchronized blocks/methods:
synchronized(this) { // critical section }Concurrent Collections: Use
ConcurrentHashMap,CopyOnWriteArrayList.Locks: Use
ReentrantLockfor fine-grained control.Atomic Variables: Use
AtomicInteger,AtomicReferencefor atomic operations.Avoid deadlocks: Always acquire locks in consistent order.
✅ Modern Java encourages lock-free structures and immutability where possible.
3. What’s your approach for debugging memory leaks?
Steps:
Identify symptoms: High heap usage,
OutOfMemoryError, slow performance.Analyze heap dumps: Use tools like VisualVM, Eclipse MAT, JProfiler.
Check references: Look for unreleased objects, static collections, caches.
Fix common causes:
Remove unused listeners or callbacks
Use
WeakReferencewhere neededClear collections properly
Test thoroughly: Run under load to confirm memory usage stabilizes.
4. How to ensure thread safety without performance issues?
Scenario: High-concurrency application.
Approach:
Prefer immutable objects to avoid synchronization overhead.
Use concurrent collections (
ConcurrentHashMap,ConcurrentLinkedQueue) instead of synchronized versions.Minimize synchronized blocks to only critical sections.
Use atomic variables for counters or flags.
Consider ReadWriteLock if reads dominate writes.
✅ Key: Balance thread safety vs performance.
5. Explain a situation where you used Java 8 features to simplify code
Example Answer:
“In a recent project, we had a list of employees and needed to filter those in a specific department, sort by salary, and collect names. Using Java 8 Streams and lambdas, I could do it in one readable statement instead of nested loops:
List<String> names = employees.stream() .filter(e -> e.getDepartment().equals("Engineering")) .sorted(Comparator.comparing(Employee::getSalary).reversed()) .map(Employee::getName) .collect(Collectors.toList());This approach reduced boilerplate code, improved readability, and was easy to maintain.”
Wrapping Up
This guide covers all essential Core Java concepts, coding patterns, and real-world scenarios needed to excel in Java interviews in 2025. Use it to strengthen fundamentals, improve problem-solving, and confidently tackle interviews.





