Core Java Interview Questions
Whether you are preparing for your first software role or targeting a senior engineer position, Java interviews tend to revisit the same foundational concepts — sometimes shallow, sometimes deep. This section collects the most commonly asked Core Java questions, explains the reasoning interviewers are looking for, and points you to focused sub-pages on OOP, Collections, and Concurrency.
What Interviewers Actually Test
Java interviews are rarely just “name the method.” Interviewers want to see that you understand why the language works the way it does. The questions cluster around a few recurring themes:
- Language fundamentals — types, scope, memory, pass-by-value
- Object-oriented design — inheritance, polymorphism, abstraction, encapsulation
- Core APIs — Strings, exceptions, I/O, Collections
- Concurrency — threads, locks, the Java Memory Model
- Modern Java — generics, lambdas, streams, records (Java 16+), virtual threads (Java 21)
The questions below are the ones that come up most often, across both phone screens and on-site rounds.
Frequently Asked Core Java Questions
1. Is Java pass-by-value or pass-by-reference?
Java is always pass-by-value. For primitives, the value itself is copied. For objects, the reference (memory address) is copied — meaning you can mutate the object’s fields inside a method, but you cannot make the caller’s variable point to a different object.
public class PassByValue {
static void tryToReassign(StringBuilder sb) {
sb.append(" World"); // visible to caller — same object
sb = new StringBuilder("X"); // NOT visible — local copy only
}
public static void main(String[] args) {
StringBuilder s = new StringBuilder("Hello");
tryToReassign(s);
System.out.println(s); // Hello World
}
}
Output:
Hello World
See Call by Value for the full breakdown.
2. What is the difference between == and .equals()?
== compares references (are both variables pointing to the exact same object in memory?). .equals() compares logical content (do the two objects represent the same value?).
public class EqualityDemo {
public static void main(String[] args) {
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false — different objects
System.out.println(a.equals(b)); // true — same content
}
}
Output:
false
true
Tip: Always override both
equals()andhashCode()together. Objects that are.equals()must return the samehashCode(), otherwiseHashMapandHashSetwill behave incorrectly.
3. Why is String immutable in Java?
Once created, a String object’s character sequence can never change. Three key reasons:
- Security — class names, network URLs, and file paths are passed as Strings. Mutability would open attack vectors.
- String Pool efficiency — because Strings are immutable, the JVM can safely cache them in the String Pool. Multiple variables can share the same literal without risk.
- Thread safety — an immutable object is inherently safe to share between threads with no synchronization.
String s = "Java";
s.concat(" 21"); // returns a NEW String; s is unchanged
System.out.println(s); // Java
Output:
Java
Read more at Why String is Immutable.
4. What is the difference between final, finally, and finalize?
| Keyword / Method | Where it lives | What it does |
|---|---|---|
final | modifier on class/method/variable | Prevents inheritance / overriding / reassignment |
finally | exception handling block | Always executes after try/catch, used for cleanup |
finalize() | Object method | Called by GC before collecting an object — deprecated in Java 9, removed in Java 18 |
public class FinalDemo {
public static void main(String[] args) {
final int MAX = 100; // constant — cannot reassign
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Caught: " + e.getMessage());
} finally {
System.out.println("finally always runs");
}
}
}
Output:
Caught: / by zero
finally always runs
Details: final Keyword, finally Block, final vs finally vs finalize.
5. What is autoboxing and unboxing?
Autoboxing is the automatic conversion of a primitive (e.g. int) to its wrapper class (Integer). Unboxing is the reverse. The compiler inserts the conversion calls invisibly.
import java.util.ArrayList;
public class AutoboxDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(42); // autoboxing: int → Integer
int val = list.get(0); // unboxing: Integer → int
System.out.println(val);
}
}
Output:
42
Warning: Autoboxing inside tight loops creates many short-lived objects. Prefer primitive arrays or streams when performance matters.
Full page: Autoboxing & Unboxing.
6. What is the difference between checked and unchecked exceptions?
| Checked | Unchecked | |
|---|---|---|
| Extends | Exception (not RuntimeException) | RuntimeException |
| Must handle? | Yes — compile error if ignored | No — optional |
| Examples | IOException, SQLException | NullPointerException, ArrayIndexOutOfBoundsException |
import java.io.*;
public class ExceptionTypes {
// checked — compiler forces you to declare or handle it
static void readFile() throws IOException {
new FileReader("missing.txt"); // IOException is checked
}
public static void main(String[] args) {
String s = null;
// unchecked — no compiler warning
System.out.println(s.length()); // NullPointerException at runtime
}
}
More on the topic: Exception Handling, Custom Exceptions.
7. Explain static vs instance members
A static member belongs to the class — it is shared across all instances and exists even before any object is created. An instance member belongs to a specific object.
public class Counter {
static int total = 0; // shared across all Counter objects
int id; // unique per object
Counter() {
total++;
this.id = total;
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
System.out.println("Total: " + Counter.total); // 2
System.out.println("c1.id: " + c1.id); // 1
System.out.println("c2.id: " + c2.id); // 2
}
}
Output:
Total: 2
c1.id: 1
c2.id: 2
See static Keyword for the full picture.
8. What is the Java Memory Model (JMM)?
The JMM defines the rules for how threads interact through memory. Key guarantees:
- Visibility — changes made by one thread are not guaranteed to be visible to another unless there is a happens-before relationship.
volatile— declares that reads/writes go directly to main memory, establishing happens-before between writer and reader.synchronized— establishes happens-before at monitor enter/exit, ensuring both visibility and atomicity.
public class VolatileDemo {
private static volatile boolean stop = false;
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
while (!stop) { /* spin */ }
System.out.println("Stopped");
});
worker.start();
Thread.sleep(100);
stop = true; // visible to worker because of volatile
}
}
Read: Java Memory Model, volatile Keyword.
9. What is the difference between an abstract class and an interface?
This is one of the most common OOP questions. The short answer: use an abstract class when you want to share state or partial implementation; use an interface when you want to define a contract that unrelated classes can implement.
| Feature | Abstract Class | Interface |
|---|---|---|
| Multiple inheritance | No | Yes (multiple interfaces) |
| Constructor | Yes | No |
| Instance fields | Yes | No (only static final) |
| Default methods | Yes (Java 8+) | Yes (Java 8+) |
| Access modifiers on methods | Any | public by default |
See Abstract Class vs Interface for detailed examples.
10. What are lambda expressions and when should you use them?
Introduced in Java 8, a lambda is a concise way to pass behavior as data. It implements a functional interface — an interface with exactly one abstract method.
import java.util.*;
public class LambdaDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
// Before Java 8
Collections.sort(names, new Comparator<String>() {
public int compare(String a, String b) { return a.compareTo(b); }
});
// Java 8+ lambda
names.sort((a, b) -> a.compareTo(b));
System.out.println(names);
}
}
Output:
[Alice, Bob, Charlie]
Deep dive: Lambda Expressions, Stream API.
Tips for Answering Java Interview Questions
- Lead with the “why.” Don’t just say what something does — explain the design decision behind it.
- Use concrete examples. Saying “immutability helps with thread safety” lands better if you sketch a two-sentence example.
- Acknowledge trade-offs. Every Java feature has a cost. Mentioning them shows senior-level thinking.
- Know which Java version introduced a feature. Saying “records were added in Java 16” signals that you follow the ecosystem.
In This Section
- OOP Interview Questions — Inheritance, polymorphism, encapsulation, abstraction, and classic design traps.
- Collections Interview Questions — HashMap internals,
ArrayListvsLinkedList, ordering,ComparablevsComparator, and more. - Concurrency Interview Questions — Threads, locks,
volatile, deadlock,ExecutorService, and the Java Memory Model.
Related Topics
- OOP Concepts — Brush up on the four pillars before your interview.
- Exception Handling — Checked vs unchecked, propagation, and custom exceptions explained.
- Collections Framework — The full map of List, Set, Queue, and Map implementations.
- Lambda Expressions — Functional-style Java that every modern interview covers.
- Java Memory Model — Essential for senior-level concurrency questions.
- Java Best Practices — Write the kind of code interviewers want to see.