Skip to main content

Command Palette

Search for a command to run...

Core Java Interview Questions: Complete Guide with Answers and Examples

Updated
37 min read
Core Java Interview Questions: Complete Guide with Answers and Examples
A

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:

  1. Encapsulation – Bundling data and methods that operate on that data into a single unit (class).
    Example: Private fields with public getters/setters.

  2. Abstraction – Hiding internal implementation details and exposing only essential features.
    Example: Abstract classes and interfaces.

  3. Inheritance – Reusing properties and methods from an existing class into a new class.
    Example: class Dog extends Animal

  4. Polymorphism – 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

FeatureAbstractionEncapsulation
PurposeFocuses on hiding implementation detailsFocuses on bundling data and behavior
Achieved ByAbstract classes and interfacesAccess modifiers (private, public, etc.)
Concerned WithDesign levelImplementation level
ExampleHiding database connection details behind an interfaceMaking 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:

  1. Compile-time polymorphism (Method Overloading):

    • Same method name, different parameter lists.

    • Resolved at compile-time.

    void show(int a) {}
    void show(String b) {}
  1. 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?

FeatureMethod OverloadingMethod Overriding
WhenCompile-timeRuntime
Class RelationshipSame classParent-child classes
ParametersMust differ in type/number/orderMust be same
Return TypeCan differMust be same or covariant
Static BindingYesNo (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

FeatureInterfaceAbstract Class
InheritanceMultiple allowedSingle allowed
ContainsAbstract methods + constants (Java 8+: default & static methods too)Can have abstract & concrete methods
Variablespublic static final by defaultCan be instance variables
ConstructorNot allowedAllowed
Use CaseWhen defining behavior/contractWhen 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.

ComponentFull FormPurpose
JVMJava Virtual MachineExecutes Java bytecode
JREJava Runtime EnvironmentContains JVM + libraries required to run Java apps
JDKJava Development KitContains 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?

AspectHeapStack
StoresObjects, instance variablesLocal variables, method calls
Shared?Shared among all threadsEach thread has its own stack
LifetimeExists until object is garbage collectedExists until method completes
Managed ByGarbage CollectorJVM automatically manages
Access SpeedSlowerFaster

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 cause OutOfMemoryError: 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:

  1. JVM identifies unreachable objects (not referenced anywhere).

  2. GC frees that memory space.

  3. 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-resources for closing streams.

  • Implement AutoCloseable for 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.

ModifierWithin ClassWithin PackageSubclass (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:

  1. Static variables.

  2. Static blocks (in order of appearance).

  3. Constructors (when object is created).

Exception Handling

1. Checked vs Unchecked Exceptions?

TypeChecked ExceptionUnchecked Exception
InheritanceSubclass of Exception (excluding RuntimeException)Subclass of RuntimeException
Checked atCompile-timeRuntime
Handling Required?Must be handled or declared using throwsOptional
ExamplesIOException, SQLException, FileNotFoundExceptionNullPointerException, 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?

Keywordthrowthrows
PurposeUsed to actually throw an exceptionDeclares that a method may throw exceptions
Usage PlaceInside method bodyIn method signature
FollowsSingle exception instanceOne or more exception classes
Examplethrow 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 catch block

  • A finally block

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 return is used inside try or catch
    ❌ Not executed if JVM exits via System.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:

  1. Extend Exception (for checked) or RuntimeException (for unchecked).

  2. 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?

FeatureListSetMap
StoresOrdered collection of elementsUnique elements (no duplicates)Key-value pairs
DuplicatesAllowedNot allowedKeys: not allowed, Values: allowed
OrderMaintains insertion orderDepends on implementationDepends on implementation
ImplementationsArrayList, LinkedList, VectorHashSet, LinkedHashSet, TreeSetHashMap, TreeMap, LinkedHashMap

Example:

List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<Integer, String> map = new HashMap<>();

2. ArrayList vs LinkedList?

AspectArrayListLinkedList
Data StructureDynamic arrayDoubly linked list
Access TimeO(1) for index-based accessO(n) traversal required
Insertion/Deletion (middle)O(n)O(1) if node reference known
Memory UsageLess (compact)More (extra node references)
Use CaseRandom accessFrequent insertions/deletions

Example:

  • Use ArrayList when reads are frequent.

  • Use LinkedList when insertions/removals are frequent.

3. HashMap vs Hashtable?

FeatureHashMapHashtable
Thread-SafetyNot synchronizedSynchronized
Null Keys/ValuesAllows one null key, multiple null valuesDoesn’t allow nulls
PerformanceFaster (no locking)Slower (locks entire table)
Introduced InJava 1.2Java 1.0
Preferred?Yes, in modern JavaLegacy 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:

  1. Key’s hashCode() is computed.

  2. The hash is mapped to an index in the bucket array ((n - 1) & hash).

  3. Each bucket holds a linked list or tree (Java 8+).

  4. On put():

    • If key exists → value replaced.

    • If not → new node added.

  5. On get():

    • Hash computed → bucket located → key compared using equals().

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?

TypeBehaviorExample Collections
Fail-FastThrows ConcurrentModificationException if the collection is modified while iteratingArrayList, HashMap
Fail-SafeWorks on a clone or snapshot of the collectionConcurrentHashMap, 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 Hashtable under multithreading.

Example:

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);

8. TreeMap vs HashMap?

FeatureHashMapTreeMap
OrderNo orderingSorted (natural/comparator)
ImplementationHash tableRed-Black tree
Null KeysAllows oneDoesn’t allow null key
PerformanceO(1) averageO(log n)
Use CaseFast lookupsSorted 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?

FeatureArrayListVector
SynchronizationNot synchronizedSynchronized
PerformanceFasterSlower (locks every method)
Introduced InJava 1.2Java 1.0 (legacy)
GrowthGrows 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?

FeatureProcessThread
DefinitionIndependent program in executionSmallest unit of a process
MemoryHas its own memory spaceShares memory with other threads of same process
CommunicationInter-process communication is complexEasier via shared objects
Failure ImpactOne process crash doesn’t affect othersThread crash may affect whole process
ExampleRunning two Java programsTwo 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:

  1. Extend Thread class

     class MyThread extends Thread {
         public void run() {
             System.out.println("Thread running...");
         }
     }
     new MyThread().start();
    
  2. Implement Runnable interface

     class MyTask implements Runnable {
         public void run() {
             System.out.println("Running via Runnable");
         }
     }
     new Thread(new MyTask()).start();
    
  3. Use ExecutorService or Callable (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?

FeatureThreadRunnable
InheritanceRequires extending ThreadCan be implemented along with other interfaces
Code ReuseLess flexibleMore flexible (no multiple inheritance issue)
PreferredFor small/simple useRunnable 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:

  1. New – Created but not started (new Thread()).

  2. Runnable – Ready to run, waiting for CPU (start() called).

  3. Running – Currently executing.

  4. Blocked/Waiting – Waiting for a resource or another thread.

  5. Terminated – Execution completed or stopped.

Example:

Thread t = new Thread(() -> {});
t.start();  // Runnable

5. Difference between wait, sleep, join?

MethodDefined InReleases Lock?Purpose
wait()Object class✅ YesWaits until notified (notify() / notifyAll())
sleep()Thread class❌ NoPauses execution for given time
join()Thread class❌ NoWaits 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 or AtomicInteger.

9. Difference between ExecutorService and Thread?

AspectThreadExecutorService
CreationManually create and start threadsManages thread pool automatically
ReusabilityOne-time useThreads are reused
PerformanceHigher overheadMore efficient for multiple tasks
IntroducedJava 1.0Java 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 boolean

  • Function<T, R> → transforms T to R

  • Consumer<T> → accepts and performs action

  • Supplier<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()?

MethodPurposeExample
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() and flatMap()

✅ 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::staticMethod

  • Instance method → object::instanceMethod

  • Constructor → 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, LocalDateTime

  • ZonedDateTime

  • Period, Duration

  • DateTimeFormatter

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?

FeatureStringStringBuilderStringBuffer
MutabilityImmutableMutableMutable
Thread-safetyNot thread-safeNot thread-safeThread-safe (synchronized)
PerformanceSlower (creates new objects)Faster (no synchronization)Slightly slower (synchronization overhead)
Use CaseWhen data doesn’t changeSingle-threaded string manipulationsMulti-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:

  1. Security: Used in sensitive contexts (ClassLoader, File paths, URLs).

  2. Thread-safety: Immutable objects can be shared safely between threads.

  3. Caching: Hash code of a string is cached; immutability ensures it’s consistent.

  4. 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 data

  • insert() – inserts at position

  • delete() – removes substring

  • reverse() – reverses content

  • capacity() – 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:

  • StringBuilder or StringBuffer

  • Reflection (not recommended)

  • Creating a wrapper class with a mutable reference internally

Java Keywords and Modifiers

1. Difference between final, finally, and finalize?

KeywordPurposeExample
finalRestricts modificationfinal int x = 10; or final class MyClass
finallyBlock to execute after try/catchtry {…} finally {…}
finalize()Called by GC before object is destroyedprotected void finalize() {…}

Summary:

  • final → compile-time constant, prevents inheritance/overriding

  • finally → runtime block for cleanup

  • finalize() → 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?

KeywordPurposeExample
thisRefers to current objectthis.name = name;
superRefers to parent classsuper.toString();
  • this() → calls current class constructor

  • super() → calls parent class constructor

  • Both 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:

  1. Member (non-static) inner class

  2. Static nested class

  3. Local inner class

  4. Anonymous inner class

2. What are static nested classes?

  • A static nested class is declared with the static keyword.

  • 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

TypeDefinitionScopeExample
Member inner classDefined at class level (non-static)Can access outer class membersclass Outer { class Inner {} }
Static nested classDefined with static keywordOnly static members of outer classOuter.Nested nested = new Outer.Nested();
Local inner classDefined inside a methodOnly visible within methodvoid method() { class Local {} }
Anonymous inner classNo class name, used for instant implementationUsually for implementing interfaces or extending classesRunnable 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:

PrincipleDescription
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:

  1. Declare class as final.

  2. Make all fields private and final.

  3. No setters.

  4. 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:

  1. Compilation: .java source code is compiled into .class bytecode using javac.

  2. Class loading: JVM loads the .class files into memory using ClassLoaders.

  3. Bytecode verification: Ensures code is valid and doesn’t violate JVM constraints.

  4. Execution: Just-In-Time (JIT) compiler converts bytecode into native machine code for performance.

  5. Memory allocation: Objects are created in the heap; references stored in stack.

  6. 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:

  1. Loading: Loads .class file into memory using ClassLoader.

  2. Linking:

    • Verification: Ensures bytecode integrity

    • Preparation: Allocates memory for static variables

    • Resolution: Resolves symbolic references

  3. 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:

  1. Bootstrap ClassLoader: Loads core Java classes (rt.jar)

  2. Extension ClassLoader: Loads JDK extension libraries (lib/ext)

  3. Application ClassLoader: Loads classes from classpath (your code)

  4. 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 (.class file), 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 AreaPurposeExample
HeapStores objects and arraysnew Employee()
StackStores method call frames, local variablesint 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 transient keyword 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 Stringfalse.

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; // autoboxing
    
  • Unboxing: Wrapper class → primitive

      Integer a = 20;
      int b = a; // unboxing
    

6. What is enum in Java?

  • enum is 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, @FunctionalInterface

  • Custom 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

TypeWhen occursExample
Compile-time errorDuring compilationSyntax error, missing semicolon
Runtime errorDuring program executionNullPointerException, ArrayIndexOutOfBounds

Real-World Scenario-Based Questions

Scenario: You have a large dataset and need frequent lookups.

Approach:

  1. Choose the right data structure:

    • HashMap for O(1) key-value lookup.

    • TreeMap if sorted order is required (O(log n) lookup).

    • HashSet for unique element search.

  2. Indexing: Precompute indices for frequent queries.

  3. Use streams with parallel processing if data is very large.

  4. Avoid unnecessary object creation: Use primitives or immutable objects.

  5. 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:

  1. Synchronized blocks/methods:

     synchronized(this) {
         // critical section
     }
    
  2. Concurrent Collections: Use ConcurrentHashMap, CopyOnWriteArrayList.

  3. Locks: Use ReentrantLock for fine-grained control.

  4. Atomic Variables: Use AtomicInteger, AtomicReference for atomic operations.

  5. 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:

  1. Identify symptoms: High heap usage, OutOfMemoryError, slow performance.

  2. Analyze heap dumps: Use tools like VisualVM, Eclipse MAT, JProfiler.

  3. Check references: Look for unreleased objects, static collections, caches.

  4. Fix common causes:

    • Remove unused listeners or callbacks

    • Use WeakReference where needed

    • Clear collections properly

  5. Test thoroughly: Run under load to confirm memory usage stabilizes.

4. How to ensure thread safety without performance issues?

Scenario: High-concurrency application.

Approach:

  1. Prefer immutable objects to avoid synchronization overhead.

  2. Use concurrent collections (ConcurrentHashMap, ConcurrentLinkedQueue) instead of synchronized versions.

  3. Minimize synchronized blocks to only critical sections.

  4. Use atomic variables for counters or flags.

  5. 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.