β˜• Java Interview Guide

Java Basics & JVM

What is Java and what are its key features?

Java is a high-level, object-oriented programming language designed to have as few implementation dependencies as possible.

Key Features of Java:

How does the JVM work?

The Java Virtual Machine (JVM) is the runtime environment for executing Java bytecode.

JVM Components:

Data Types & Variables

What are the different data types in Java?

Primitive Data Types (8 types):

Type Size Range Default Value
byte 1 byte -128 to 127 0
short 2 bytes -32,768 to 32,767 0
int 4 bytes -2Β³ΒΉ to 2Β³ΒΉ-1 0
long 8 bytes -2⁢³ to 2⁢³-1 0L
float 4 bytes IEEE 754 0.0f
double 8 bytes IEEE 754 0.0d
char 2 bytes 0 to 65,535 '\u0000'
boolean 1 bit true/false false

Non-Primitive Data Types:

Object-Oriented Programming Concepts

What are the four pillars of OOP?

1. Encapsulation

Wrapping data (variables) and methods that operate on the data into a single unit (class). It hides the internal details and provides controlled access through public methods.

public class Student {
    private String name;  // Private data member
    private int age;
    
    // Public getter method
    public String getName() {
        return name;
    }
    
    // Public setter method with validation
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
}

2. Inheritance

Mechanism by which one class acquires the properties and methods of another class.

// Parent class
class Animal {
    protected String name;
    
    public void eat() {
        System.out.println(name + " is eating");
    }
}

// Child class inheriting from Animal
class Dog extends Animal {
    public void bark() {
        System.out.println(name + " is barking");
    }
}

3. Polymorphism

Ability of objects to take multiple forms. Same method name can have different implementations.

// Method Overriding (Runtime Polymorphism)
class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

4. Abstraction

Hiding implementation details while showing only essential features.

// Abstract class
abstract class Shape {
    protected String color;
    
    // Abstract method - must be implemented by subclasses
    public abstract double calculateArea();
    
    // Concrete method
    public void setColor(String color) {
        this.color = color;
    }
}

class Circle extends Shape {
    private double radius;
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

Java Collections Framework

What is the Collections Framework in Java?

The Java Collections Framework is a unified architecture for representing and manipulating collections of objects.

Core Interfaces:

Collection Hierarchy:

Collection
β”œβ”€β”€ List (ArrayList, LinkedList, Vector)
β”œβ”€β”€ Set (HashSet, LinkedHashSet, TreeSet)
└── Queue (PriorityQueue, ArrayDeque)

Map (HashMap, LinkedHashMap, TreeMap, Hashtable)

List Interface

What are the main List implementations?

1. ArrayList

2. LinkedList

3. Vector

// ArrayList Example
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
arrayList.add(1, "JavaScript"); // Insert at index 1

// LinkedList Example
List<String> linkedList = new LinkedList<>();
linkedList.addFirst("First");
linkedList.addLast("Last");

// Iteration
for (String item : arrayList) {
    System.out.println(item);
}

Multithreading & Concurrency

How do you create and manage threads in Java?

1. Extending Thread Class

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Thread: " + Thread.currentThread().getName() + ", Count: " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Thread interrupted");
            }
        }
    }
}

// Usage
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();

2. Implementing Runnable Interface

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Runnable: " + Thread.currentThread().getName() + ", Count: " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Thread interrupted");
            }
        }
    }
}

// Usage
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());
thread1.start();
thread2.start();

3. Using Lambda Expressions (Java 8+)

// Lambda expression with Runnable
Thread thread = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("Lambda Thread: " + i);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
});
thread.start();

Thread Lifecycle:

Synchronization

What is synchronization in Java?

Synchronization is a mechanism to control access to shared resources by multiple threads to prevent race conditions and data inconsistency.

1. Synchronized Methods

class Counter {
    private int count = 0;
    
    // Synchronized method
    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

// Usage
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
    for (int i = 0; i < 1000; i++) {
        counter.increment();
    }
});
Thread t2 = new Thread(() -> {
    for (int i = 0; i < 1000; i++) {
        counter.increment();
    }
});
t1.start();
t2.start();

2. Synchronized Blocks

class BankAccount {
    private double balance = 1000;
    private final Object lock = new Object();
    
    public void withdraw(double amount) {
        synchronized (lock) {
            if (balance >= amount) {
                System.out.println("Withdrawing: " + amount);
                balance -= amount;
                System.out.println("Remaining balance: " + balance);
            } else {
                System.out.println("Insufficient balance");
            }
        }
    }
}

3. Static Synchronization

class Utils {
    private static int counter = 0;
    
    // Static synchronized method
    public static synchronized void incrementCounter() {
        counter++;
    }
    
    // Synchronized block on class object
    public static void incrementCounterBlock() {
        synchronized (Utils.class) {
            counter++;
        }
    }
}

Lambda Expressions (Java 8+)

What are Lambda expressions?

Lambda expressions provide a concise way to represent anonymous functions. They enable functional programming in Java.

Lambda Syntax:

// Basic syntax: (parameters) -> expression
// Or: (parameters) -> { statements; }

// Examples:
() -> System.out.println("Hello World");           // No parameters
(x) -> x * x;                                     // Single parameter
(x, y) -> x + y;                                  // Multiple parameters
(x, y) -> {                                       // Block body
    int sum = x + y;
    return sum;
};

Using Lambda with Collections:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// Before Java 8 (Anonymous inner class)
names.forEach(new Consumer<String>() {
    @Override
    public void accept(String name) {
        System.out.println(name);
    }
});

// With Lambda expression
names.forEach(name -> System.out.println(name));

// Method reference (even more concise)
names.forEach(System.out::println);

// Filtering with lambda
List<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());

Streams API

What is the Streams API in Java 8?

Streams API provides a functional approach to processing collections of data. It allows for declarative data processing with operations like filter, map, and reduce.

Stream Operations:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Filter even numbers, square them, and collect to list
List<Integer> evenSquares = numbers.stream()
    .filter(n -> n % 2 == 0)        // Intermediate operation
    .map(n -> n * n)                // Intermediate operation
    .collect(Collectors.toList());   // Terminal operation

// Find sum of all numbers
int sum = numbers.stream()
    .mapToInt(Integer::intValue)
    .sum();

// Find first even number
Optional<Integer> firstEven = numbers.stream()
    .filter(n -> n % 2 == 0)
    .findFirst();

// Group by even/odd
Map<Boolean, List<Integer>> groupedByEvenOdd = numbers.stream()
    .collect(Collectors.groupingBy(n -> n % 2 == 0));

Parallel Streams:

// Process large datasets in parallel
List<String> largeList = // ... large list
long count = largeList.parallelStream()
    .filter(s -> s.length() > 10)
    .count();

Exception Handling

How does exception handling work in Java?

Java uses try-catch-finally blocks to handle exceptions. Exceptions are objects that represent errors or exceptional conditions.

Exception Hierarchy:

Throwable
β”œβ”€β”€ Error (OutOfMemoryError, StackOverflowError)
└── Exception
    β”œβ”€β”€ RuntimeException (Unchecked)
    β”‚   β”œβ”€β”€ NullPointerException
    β”‚   β”œβ”€β”€ ArrayIndexOutOfBoundsException
    β”‚   └── IllegalArgumentException
    └── Checked Exceptions
        β”œβ”€β”€ IOException
        β”œβ”€β”€ SQLException
        └── ClassNotFoundException

Try-Catch-Finally Example:

public class ExceptionExample {
    public static void divideNumbers(int a, int b) {
        try {
            int result = a / b;
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Error: Division by zero");
            e.printStackTrace();
        } finally {
            System.out.println("Finally block always executes");
        }
    }
    
    // Method that throws checked exception
    public static void readFile(String filename) throws IOException {
        FileReader file = new FileReader(filename);
        // File operations
        file.close();
    }
}

Custom Exceptions:

// Custom checked exception
class InsufficientFundsException extends Exception {
    private double amount;
    
    public InsufficientFundsException(double amount) {
        super("Insufficient funds: " + amount);
        this.amount = amount;
    }
    
    public double getAmount() {
        return amount;
    }
}

// Usage
public void withdraw(double amount) throws InsufficientFundsException {
    if (amount > balance) {
        throw new InsufficientFundsException(amount);
    }
    balance -= amount;
}

Spring Framework

What is Spring Framework and its core concepts?

Spring is a comprehensive framework for enterprise Java development that provides infrastructure support for developing Java applications.

Core Spring Concepts:

Dependency Injection Example:

// Service class
@Service
public class UserService {
    private UserRepository userRepository;
    
    // Constructor injection (recommended)
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public User findById(Long id) {
        return userRepository.findById(id);
    }
}

// Repository interface
@Repository
public interface UserRepository {
    User findById(Long id);
    void save(User user);
}

// Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
}

JVM Architecture

What is the architecture of JVM?

The Java Virtual Machine (JVM) is a runtime environment that executes Java bytecode. It provides platform independence and memory management.

JVM Architecture Components:

JVM Architecture
β”œβ”€β”€ Class Loader Subsystem
β”‚   β”œβ”€β”€ Bootstrap ClassLoader
β”‚   β”œβ”€β”€ Extension ClassLoader
β”‚   └── Application ClassLoader
β”œβ”€β”€ Runtime Data Areas
β”‚   β”œβ”€β”€ Method Area (Metaspace in Java 8+)
β”‚   β”œβ”€β”€ Heap Memory
β”‚   β”‚   β”œβ”€β”€ Young Generation (Eden, S1, S2)
β”‚   β”‚   └── Old Generation (Tenured)
β”‚   β”œβ”€β”€ Stack Memory (per thread)
β”‚   β”œβ”€β”€ PC Registers (per thread)
β”‚   └── Native Method Stack
└── Execution Engine
    β”œβ”€β”€ Interpreter
    β”œβ”€β”€ Just-In-Time (JIT) Compiler
    └── Garbage Collector

1. Class Loader Subsystem:

2. Runtime Data Areas:

3. Execution Engine:

// JVM Execution Process
Source Code (.java) 
    ↓ javac compiler
Bytecode (.class)
    ↓ ClassLoader
Loaded Classes in Method Area
    ↓ Execution Engine
    β”œβ”€β”€ Interpreter (line by line execution)
    └── JIT Compiler (compile to native code)
    ↓
Native Machine Code Execution

JIT Compiler Optimization:

Class Loading Process:

// Class Loading Phases
1. Loading: Read .class file and create Class object
2. Linking:
   a. Verification: Verify bytecode correctness
   b. Preparation: Allocate memory for static variables
   c. Resolution: Replace symbolic references with direct references
3. Initialization: Execute static initializers and static blocks

// Example
public class Example {
    static int count = 10;        // Prepared with default value 0
    static {                      // Executed during initialization
        count = 20;
        System.out.println("Static block executed");
    }
}

JVM Memory Management

How does Java manage memory?

Java memory is divided into several regions, each serving different purposes in program execution.

Memory Areas:

Heap Memory Structure:

Heap Memory
β”œβ”€β”€ Young Generation
β”‚   β”œβ”€β”€ Eden Space (new objects)
β”‚   β”œβ”€β”€ Survivor Space 1 (S1)
β”‚   └── Survivor Space 2 (S2)
└── Old Generation (Tenured Space)
    └── Long-lived objects

Garbage Collection Types:

Memory Best Practices:

public class MemoryBestPractices {
    // Avoid memory leaks
    private static final Map<String, Object> cache = new HashMap<>();
    
    // Use StringBuilder for string concatenation
    public String buildString(List<String> items) {
        StringBuilder sb = new StringBuilder();
        for (String item : items) {
            sb.append(item);
        }
        return sb.toString();
    }
    
    // Close resources properly
    public void readFile(String filename) {
        try (FileReader reader = new FileReader(filename)) {
            // File operations
        } catch (IOException e) {
            e.printStackTrace();
        } // Auto-close with try-with-resources
    }
}

Java Best Practices

What are some Java coding best practices?