Java - Interview preparation guide
Thilan Dissanayaka Interview Guides March 14, 2020

Java - Interview preparation guide

  • Keywords
  • Data types and Operators
  • Strings
  • Threads
  • OOP in Java
  • Exceptions

Java Keywords

What is the use of final keyword?

The final keyword in Java is used to indicate that a variable, method, or class cannot be modified in a certain way:

  1. Final Variable Once assigned, the value of a final variable cannot be changed. It acts like a constant.

For objects, it means the reference cannot be changed, but the object’s internal state can still be modified.

final int x = 10;
x = 20; // Compilation error

final List<String> list = new ArrayList<>();
list.add(\"hello\"); // Allowed
list = new ArrayList<>(); // Not allowed
  1. Final Method A method marked as final cannot be overridden by subclasses.

Used to prevent altering critical behavior in subclass.

class A {
    final void show() {
        System.out.println(\"A's show\");
    }
}

class B extends A {
    void show() { } // Compilation error
}
  1. Final Class A final class cannot be subclassed.

Often used for security or design reasons (e.g., Java’s String class is final).

final class A {
}

class B extends A { } // Compilation error

What is transient keyword in Java?

The transient keyword is used with variables when serializing an object.

When an object is serialized, all non-transient variables are saved.

Transient variables are ignored during serialization.

Commonly used for sensitive data like passwords or non-serializable fields.

class User implements Serializable {
    String username;
    transient String password; // won't be saved during serialization
}

When this object is deserialized, the password field will be null.

  • It is used to exclude a variable from serialization.
  • Useful when sensitive or temporary data should not be stored.

What is volatile keyword?

The volatile keyword is used in multithreaded programming.

It ensures that the value of the variable is always read from main memory, not from a thread-local cache.

Guarantees visibility: When one thread updates a volatile variable, the new value is visible to all other threads immediately.

class SharedResource {
    volatile boolean flag = false;

    void writer() {
        flag = true;
    }

    void reader() {
        if (flag) {
            // do something
        }
    }
}

Without volatile, changes made by one thread might not be visible to another due to CPU caching or compiler optimization.

  • Ensures visibility of changes to variables across threads.
  • Prevents the JVM from caching the variable locally.

Java Data types

What are the main data types in Java?

Java has two types of data types:

  • Primitive types: byte, short, int, long, float, double, char, boolean
  • Reference types: Objects, Arrays, Interfaces, Enums

What is the difference between int and Integer?

  • int is a primitive data type.
  • Integer is a wrapper class that allows int to be used as an object and provides utility methods.

What are the types of operators in Java?

  • Arithmetic (+, -, *, /, %)
  • Relational (==, !=, <, >, <=, >=)
  • Logical (&&,   , !)
  • Bitwise (&, , ^, ~, «, »)
  • Assignment (=, +=, -=, etc.)
  • Unary (+, -, ++, –)
  • Ternary (condition ? true : false)

Difference between == and .equals() in Java?

  • == checks for reference equality (whether they point to the same object).
  • .equals() checks for content equality, if overridden (e.g., in String).

Java Strings

What is the difference between String, StringBuilder, and StringBuffer?

Feature Mutability Performance Use case
String No Slow (for changes) Constant strings
StringBuilder No Fast Single-threaded string manipulation
StringBuffer Yes Slower than StringBuilder Multi-threaded environments
        String str = \"Hello\";
        str.concat(\" World\");
        System.out.println(str); // Output: Hello


        StringBuilder sb = new StringBuilder(\"Hello\");
        sb.append(\" World\");
        System.out.println(sb); // Output: Hello World

        StringBuffer sb2 = new StringBuffer(\"Hello\");
        sb2.append(\" World\");
        System.out.println(sb2); // Output: Hello World

concat(" World") returns a new string, but it’s not stored, so str remains "Hello". To get "Hello World", you’d need: str = str.concat(" World");

StringBuilder modifies the original object — much more memory-efficient and faster for repeated modifications (like in loops).

Why is String immutable in Java?

  • For security (used in class loading, file paths, network connections)
  • For performance (string literals are interned)
  • For thread safety (shared across threads safely)
  • Because hashCode is cached, it improves the performance of HashMap

What Happens When You Modify a String?

In Java, String is immutable, meaning once a String object is created, its value cannot be changed.

String s = \"hello\";
s = s + \" world\";

Here’s what happens step-by-step:

"hello" is stored in the string pool, and s refers to it.

" world" is also stored in the string pool.

The + operator creates a new String object with the value "hello world".

The variable s now points to this new object.

The original "hello" string remains in memory and unchanged.

Why is this important?

This behavior ensures thread safety and consistency.

It avoids accidental changes to shared strings.

How Does Immutability Help with String Pooling?

The string pool is a special area in the Java heap where interned strings are stored. When you create a string like:

String a = \"test\";
String b = \"test\";

Both a and b point to the same object in the pool because:

Strings are immutable.

There is no risk that a or b will modify the shared string.

If strings were mutable:

Changing the content via one reference would affect all other references.

String pooling would be unsafe and unreliable.

Immutability ensures:

Memory efficiency: fewer duplicate strings.

Faster comparison: reference equality (==) works for interned strings.

Thread safety: multiple threads can safely share strings without synchronization.

What are some commonly used String methods?

  • length()
  • charAt(index)
  • substring(start, end)
  • indexOf(), lastIndexOf()
  • equals(), equalsIgnoreCase()
  • contains(), startsWith(), endsWith()
  • replace(), replaceAll()
  • split(delimiter)
  • toLowerCase(), toUpperCase()
  • trim()

What is the difference between == and .equals() with strings?

  • == checks reference equality (memory address)
  • .equals() checks actual content of the string
String a = \"hello\";
String b = \"hello\";
String c = new String(\"hello\");

System.out.println(a == b); // true (both point to the same object in string pool)
System.out.println(a == c); // false (c is a new object in heap memory)

System.out.println(a.equals(b)); // true (same content)
System.out.println(a.equals(c)); // true (same content)

What is string interning?

Interning is a method of storing only one copy of each distinct string literal in a pool. When a string is interned using intern(), it is added to the string pool.

What is the use of intern() method?

It returns a canonical representation of the string from the string pool. Useful in memory optimization.

String a = new String(\"hello\");
String b = a.intern();
String c = \"hello\";
System.out.println(b == c); // true

How are regular expressions used in Java?

Using the Pattern and Matcher classes from java.util.regex.

Pattern pattern = Pattern.compile(\"\\d+\");
Matcher matcher = pattern.matcher(\"123abc\");
System.out.println(matcher.find()); // true

What are some common regex patterns?

  • . – any character
  • \d – digit
  • \D – non-digit
  • \w – word character
  • \s – whitespace
  • * – zero or more
    • – one or more
  • ? – zero or one
  • [abc] – a, b, or c
  • ^, $ – beginning or end of line

Difference between replace() and replaceAll() in String?

  • replace() works with characters or strings (literal values)
  • replaceAll() works with regular expressions
\"abc123\".replace(\"123\", \"\"); // \"abc\"
\"abc123\".replaceAll(\"\\d+\", \"\"); // \"abc\"

Java OOP Concepts

What is the difference between a class and an object?

  • A class is a blueprint or template.
  • An object is an instance of a class.
class Car {
    String color;
    void drive() {
        System.out.println(\"Driving...\");
    }
}

Car myCar = new Car(); // Object of class Car

Can we have a class without any object in Java?

Yes. A class can have only static methods/fields and still be used.

class MathUtils {
    public static int square(int x) {
        return x * x;
    }
}

int result = MathUtils.square(5); // No object needed

What is Encapsulation in Java?

Encapsulation is the process of wrapping data (variables) and methods together into a single unit (class) and restricting direct access.

class Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

What is Inheritance?

Inheritance allows a class to acquire properties and behavior of another class.

class Animal {
    void sound() {
        System.out.println(\"Animal sound\");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println(\"Woof\");
    }
}

Explain Polymorphism

Polymorphism allows one interface to be used for multiple forms.

  1. Compile-time Polymorphism (Method Overloading)
class Math {
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {
        return a + b;
    }
}
  1. Run-time Polymorphism (Method Overriding)
class Animal {
    void sound() {
        System.out.println(\"Generic sound\");
    }
}

class Cat extends Animal {
    void sound() {
        System.out.println(\"Meow\");
    }
}

What is Abstraction?

Abstraction hides internal implementation and shows only functionality.

Using abstract class

abstract class Shape {
    abstract void draw();
}

class Circle extends Shape {
    void draw() {
        System.out.println(\"Drawing circle\");
    }
}

Using interface

interface Drawable {
    void draw();
}

class Rectangle implements Drawable {
    public void draw() {
        System.out.println(\"Drawing rectangle\");
    }
}

What is a constructor?

A constructor is a special method called when an object is created.
It has the same name as the class and no return type.

class Car {
    Car() {
        System.out.println(\"Car created\");
    }
}

What are the types of constructors?

  • Default constructor: No arguments
      Car() { }
    
  • Parameterized constructor: With arguments
      Car(String model) {
          this.model = model;
      }
    
  • Copy constructor: Manually created
      Car(Car c) {
          this.model = c.model;
      }
    

What is this keyword used for?

  • Refers to the current instance of the class
  • Differentiates between local and instance variables
class Student {
    String name;
    Student(String name) {
        this.name = name; // 'this' refers to instance variable
    }
}

What is super keyword used for?

  • Refers to parent class instance
  • Used to call parent class methods/constructors
class Animal {
    void sound() {
        System.out.println(\"Generic sound\");
    }
}

class Dog extends Animal {
    void sound() {
        super.sound(); // Calls Animal's sound()
        System.out.println(\"Bark\");
    }
}

What is the difference between static and non-static members?

  • Static: Belongs to the class; shared by all instances
  • Non-static: Belongs to the object; each object has its own copy
class Example {
    static int count = 0;
    int id;

    Example(int id) {
        this.id = id;
        count++;
    }
}

Can a static method access non-static data?

No. Static methods cannot access non-static members directly.

class Test {
    int x = 10;

    static void printX() {
        // System.out.println(x); // Error: non-static variable x cannot be referenced from a static context
    }
}

Java threading

What are the different ways to create a thread in Java?

Extending Thread class

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

class MyRunnable implements Runnable {
public void run() {
System.out.println(\"Runnable running\");
}
}
new Thread(new MyRunnable()).start();

Using ExecutorService (preferred)

ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(() -> System.out.println(\"Thread pool task\"));
executor.shutdown();

What are the states in the thread lifecycle?

New

Runnable

Running

Blocked / Waiting / Timed Waiting

Terminated (Dead)

Use Thread.State enum to query a thread’s current state.

What does the synchronized keyword do?

Ensures mutual exclusion—only one thread can access a critical section at a time.

synchronized (object) {
// critical section
}

Difference between wait(), notify(), and notifyAll()?

wait() → causes the current thread to wait until another thread calls notify() or notifyAll()

notify() → wakes up one waiting thread

notifyAll() → wakes up all waiting threads

Must be called from within a synchronized block.

What is a deadlock? How to prevent it?

Deadlock occurs when two or more threads wait on each other’s resources, creating a cycle.

Prevention:

Lock ordering

Try-lock pattern

Avoid nested locks when possible

What is a race condition?

A race condition happens when two or more threads access shared data and try to change it at the same time, leading to unexpected results.

Fix: Use synchronization or atomic classes.

What is starvation?

A thread is starved when it waits indefinitely for CPU or resource access, usually due to high-priority threads monopolizing access.

What are thread-safe collection classes in Java?

Vector, Hashtable (legacy)

Collections.synchronizedList()

Concurrent Collections (preferred):

ConcurrentHashMap

CopyOnWriteArrayList

BlockingQueue

What is volatile keyword?

volatile ensures changes to a variable are visible to all threads immediately. It prevents caching of the variable’s value by any thread.

volatile boolean running = true;

What is AtomicInteger and when to use it?

It allows lock-free thread-safe operations on integers. Commonly used for counters.

AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet();

What is ReentrantLock? How is it different from synchronized?

Explicit lock from java.util.concurrent.locks

More control than synchronized (e.g., tryLock, fairness policy)

Must be manually released

ReentrantLock lock = new ReentrantLock(); lock.lock(); try { // critical section } finally { lock.unlock(); }

What is the Java Memory Model?

Defines how threads interact with memory. It specifies:

Visibility rules

Happens-before relationships

Instruction reordering

volatile, synchronized, and final interact with the JMM to ensure consistency.

What is the difference between Runnable and Callable?

Feature Runnable Callable Returns? No return value Returns a value (via Future) Throws? Cannot throw checked excep. Can throw checked exceptions

How do you use Callable with ExecutorService?

Callable task = () -> 123; Future future = executor.submit(task); Integer result = future.get(); // blocks until done

What is CompletableFuture?

It’s an enhancement over Future that supports asynchronous, non-blocking programming.

CompletableFuture.supplyAsync(() -> { return "Hello"; }).thenApply(str -> str + " World").thenAccept(System.out::println);

Java Exceptions

What is the difference between checked and unchecked exceptions?

Feature Checked Exception Unchecked Exception Inheritance Extends Exception Extends RuntimeException Compile-time check Required Not required Must handle? Yes (try-catch or throws) No, optional Examples IOException, SQLException NullPointerException, ArithmeticException

Why are some exceptions checked and others unchecked?

Checked exceptions are meant to force the programmer to handle recoverable errors, like file not found. Unchecked exceptions indicate programming bugs, like null pointer access, that should be fixed rather than caught.

What is the purpose of finally block in Java?

The finally block always executes, whether an exception occurs or not. It is used to release resources, like closing files, database connections, etc.

try {
// risky code
} catch (Exception e) {
// handle exception
} finally {
// cleanup code
}

Can a finally block override a return value?

Yes. If both the try and finally blocks have return statements, the return from finally overrides the one from try. But this is discouraged.

Difference between throw and throws?

Feature Purpose Location
throw Purpose To actually throw an exception Inside a method
throws To declare an exception In method signature
throw new IOException(); 
public void read() throws IOException

Can you throw multiple exceptions using throw?

No. throw is used to throw only one exception at a time.

How do you create a custom exception in Java?

public class MyCustomException extends Exception {
public MyCustomException(String message) {
super(message);
}
}

if (age < 18) {
throw new MyCustomException(\"Age must be 18+\");
}

Should custom exceptions extend Exception or RuntimeException?

Depends on the use case:

  • Extend Exception for checked custom exceptions (require handling).

  • Extend RuntimeException for unchecked ones (optional handling).

What are some best practices in exception handling?

  • Catch only those exceptions you can handle meaningfully.
  • Avoid catching Exception or Throwable unless absolutely necessary.
  • Always clean up resources in finally or use try-with-resources.
  • Use custom exceptions for business logic clarity.
  • Log exceptions properly — don’t silently ignore them.
  • Don’t use exceptions for flow control.

What is try-with-resources?

Introduced in Java 7, it automatically closes resources (e.g. InputStream, BufferedReader).

try (BufferedReader br = new BufferedReader(new FileReader(\"file.txt\"))) {
String line = br.readLine();
}

Java Collections

What are the main interfaces in the Java Collections Framework?

List – Ordered collection, allows duplicates. (ArrayList, LinkedList)

Set – Unordered, no duplicates. (HashSet, LinkedHashSet, TreeSet)

Map – Key-value pairs, keys are unique. (HashMap, TreeMap, LinkedHashMap)

Queue – FIFO structure. (PriorityQueue, LinkedList)

Difference between Collection and Collections?

Collection is the root interface for lists, sets, and queues.

Collections is a utility class with static methods like sort(), reverse(), synchronizedList().

Difference between ArrayList and LinkedList?

Feature ArrayList LinkedList Data structure Dynamic array Doubly linked list Access time Fast (O(1) for index) Slow (O(n)) Insert/delete Slow (shifting needed) Fast at head/tail Memory usage Less More (due to node links)

Difference between HashSet and TreeSet?

Feature HashSet TreeSet Order No order Sorted (natural or custom) Performance Faster (O(1)) Slower (O(log n)) Nulls Allows one null Allows one null if comparator supports it

Difference between HashMap, TreeMap, and LinkedHashMap?

Feature HashMap TreeMap LinkedHashMap Order No order Sorted by keys Insertion order Null keys One null key No null keys One null key Performance Fast (O(1)) Slower (O(log n)) Slower than HashMap

What’s the difference between Comparable and Comparator?

Feature Comparable Comparator Interface method compareTo(Object o) compare(Object o1, o2) Location Implemented in the class itself Implemented in separate class Used for Natural ordering Custom ordering

class Student implements Comparable { int age; public int compareTo(Student s) { return this.age - s.age; } }

How do you sort a list using Comparator?

Collections.sort(list, (a, b) -> a.name.compareTo(b.name));

Ways to iterate over a collection?

  • For-each loop
  • Iterator
  • ListIterator (supports reverse)
  • Streams (forEach)
  • Traditional for-loop (index-based)

What’s the benefit of streams?

They allow functional-style operations like filtering, mapping, and collecting, often making code shorter and more readable.

list.stream().filter(s -> s.startsWith("A")).forEach(System.out::println);

ALSO READ
Blockchain 0x000 – Understanding the Fundamentals
May 21, 2020 Web3 Development

Imagine a world where strangers can exchange money, share data, or execute agreements without ever needing to trust a central authority. No banks, no intermediaries, no single point of failure yet...

Identity and Access Management (IAM)
May 11, 2020 Identity & Access Management

Who are you — and what are you allowed to do? That's the fundamental question every secure system must answer. And it's exactly what Identity and Access Management (IAM) is built to solve.

How I built a web based CPU Simulator
May 07, 2020 Pet Projects

As someone passionate about computer engineering, reverse engineering, and system internals, I've always been fascinated by what happens "under the hood" of a computer. This curiosity led me to...

Writing a Shell Code for Linux
Apr 21, 2020 Exploit Development

Shellcode is a small piece of machine code used as the payload in exploit development. In this post, we write Linux shellcode from scratch — starting with a simple exit, building up to spawning a shell, and explaining every decision along the way.

Exploiting a Stack Buffer Overflow on Windows
Apr 12, 2020 Exploit Development

In a previous tutorial we discusses how we can exploit a buffer overflow vulnerability on a Linux machine. I wen through all theories in depth and explained each step. Now today we are going to jump...

Access Control Models
Apr 08, 2020 Identity & Access Management

Access control is one of the most fundamental concepts in security. Every time you set file permissions, assign user roles, or restrict access to a resource, you're implementing some form of access control. But not all access control is created equal...

Exploiting a  Stack Buffer Overflow  on Linux
Apr 01, 2020 Exploit Development

Have you ever wondered how attackers gain control over remote servers? How do they just run some exploit and compromise a computer? If we dive into the actual context, there is no magic happening....

Basic concepts of Cryptography
Mar 01, 2020 Cryptography

Ever notice that little padlock icon in your browser's address bar? That's cryptography working silently in the background, protecting everything you do online. Whether you're sending an email,...

Common Web Application Attacks
Feb 05, 2020 Application Security

Web applications are one of the most targeted surfaces by attackers. This is primarily because they are accessible over the internet, making them exposed and potentially vulnerable. Since these...

Remote Code Execution (RCE)
Jan 02, 2020 Application Security

Remote Code Execution (RCE) is the holy grail of application security vulnerabilities. It allows an attacker to execute arbitrary code on a remote server — and the consequences are as bad as it sounds. In this post, we'll go deep into RCE across multiple languages, including PHP, Java, Python, and Node.js.