Java interviews test whether you understand how the language actually runs—bytecode on the JVM, object lifecycle, inheritance traps, and the static/instance boundary—not whether you can recite keyword lists from memory. Experienced loops often start with fundamentals and then push into design: "Why would this cause a NullPointerException?" or "When would you pick composition over inheritance?"
This page is part one of a two-part set (53 questions here). It covers JVM basics, OOP, constructors, static members, polymorphism, and abstract classes. Continue with part two for collections, garbage collection, threading, and Java 8+ features. For a dedicated OOP and OOPs prep guide (four pillars, SOLID, design patterns, Java OOPs depth), see OOP interview questions. For C and C++ interview questions (pointers, memory, RAII), see C and C++ interview questions. For Spring Boot framework depth, see Spring Boot interview questions for experienced developers. For Selenium and Java UI automation (WebDriver, TestNG, POM), see Selenium interview questions. For full-stack integration questions, see full stack developer interviews.
Interview context and how to prepare
What do Java interviews test in part one?
Part one is the foundation layer. Interviewers use it to see whether you can reason about Java before diving into frameworks like Spring.
Topics you should expect:
| Area | What interviewers probe |
|---|---|
| Platform | JDK vs JRE vs JVM, bytecode, class loading |
| OOP | Inheritance, polymorphism, abstraction, encapsulation |
| Object model | Constructors, this/super, static vs instance |
| Design basics | Abstract classes vs interfaces, overriding rules |
How depth changes by level:
- Fresher / junior — syntax, definitions, small code traces
- Experienced — same topics with follow-ups: thread-safety, design trade-offs, production bugs
How should you use this two-part Java guide?
Use both parts as a structured drill, not a single cram session.
| Part | Coverage | When to focus |
|---|---|---|
| Part 1 (this page) | JVM, OOP, static, polymorphism, abstract classes | Week 1–2 if basics are rusty |
| Part 2 | Collections, GC, exceptions, threading, lambdas, records | Week 2–4; highest ROI for experienced roles |
Suggested split if you already ship production Java:
- ~40% on part one (fill gaps, fix misconceptions)
- ~60% on part two (collections, concurrency, modern Java)
Daily habit: For each question, answer out loud in 60–90 seconds, then open the collapsed answer and compare structure—not just keywords.
What Java fundamentals still matter in 2026?
Even with records, virtual threads, and pattern matching, interviewers still return to core concepts because production bugs still come from them.
Still high frequency:
| Concept | Why it still appears |
|---|---|
| Immutability | Thread-safety, String behavior, defensive copies |
| equals / hashCode contract | HashMap/HashSet bugs, lost keys |
| Composition over inheritance | Fragile base classes, deep hierarchies |
| Static vs instance | Shared mutable state, testability |
Modern awareness (details in part two): Records for DTOs, sealed classes for controlled hierarchies, virtual threads for I/O-heavy services.
Language trivia without a story scores poorly. Tie each answer to something you have debugged—a NullPointerException, a map lookup that "should work," a static field that leaked state across tests.
JVM, platform, and class loading
What is the difference between JDK and JRE?
Think of the JDK as the full developer toolkit and the JRE as the runtime slice needed to execute compiled programs.
| Component | Full name | What it includes |
|---|---|---|
| JDK | Java Development Kit | Compiler (javac), debugger, libraries, and a JRE |
| JRE | Java Runtime Environment | JVM + core libraries to run bytecode (no compiler) |
Interview framing:
- You develop with the JDK (
javacproduces.classfiles). - You run with the JRE/JVM (
java MyApploads bytecode). - Modern JDK distributions (11+) often ship as a single download—the JRE is not always a separate install.
A strong answer is:
The JDK is for development—it includes the compiler and tools. The JRE is the runtime that executes bytecode on the JVM. In practice I install a JDK because it contains both.
What is Java Virtual Machine (JVM)?
The JVM is the engine that loads bytecode, verifies it, and executes it. Your .java source compiles to platform-independent bytecode; a JVM implementation for your OS (Linux, Windows, macOS) runs that bytecode on real hardware.
What the JVM does at a high level:
- Load classes (via class loaders)
- Verify bytecode safety
- Execute (interpret or JIT-compile to native code)
- Manage memory (heap, stacks, garbage collection)
Each platform has its own JVM implementation, which is why Java is "write once, run anywhere" at the bytecode layer—not because .class files run natively on every CPU.
A strong answer is:
The JVM is the runtime that executes Java bytecode. It handles class loading, verification, execution, and memory management—the bridge between portable bytecode and the underlying operating system.
What are the different types of memory areas allocated by JVM?
The JVM divides memory into areas with different lifetimes and purposes. Knowing them helps you reason about leaks, stack overflows, and GC behavior.
| Memory area | Purpose |
|---|---|
| Method area (metaspace) | Class metadata, runtime constant pool, method bytecode |
| Heap | Object instances and arrays (shared across threads) |
| Stack (per thread) | Local variables, partial results, method call frames |
| PC register (per thread) | Address of the current bytecode instruction |
| Native method stack | Support for JNI / native code |
Class loaders (Bootstrap, Platform/Extension, Application) load .class files into the method area—they are not separate "memory pools" but are often discussed alongside JVM layout.
For OS-level memory visibility, see check memory usage per process on Linux.
A strong answer is:
The heap holds objects, each thread gets its own stack for locals and calls, and class metadata lives in the method area. OutOfMemoryError on the heap and StackOverflowError on deep recursion are the classic symptoms of getting these wrong.
What is JIT compiler?
JIT (Just-In-Time) compilation converts hot bytecode paths to native machine code while the program runs, instead of interpreting every instruction forever.
Why it matters in interviews:
- Cold code may start interpreted; frequently executed methods get optimized.
- This is why micro-benchmarks that run once can mislead you—JIT needs warmup.
- JVM vendors (HotSpot, GraalVM) differ in optimization details, but the concept is universal.
JIT is enabled by default on HotSpot and is a major reason Java can be competitive on long-running server workloads.
A strong answer is:
The JIT compiler translates frequently executed bytecode to native code at runtime for better performance. I mention warmup when discussing benchmarks—first runs are not representative of steady-state server load.
How Java platform is different from other platforms?
Many languages compile to native machine code for one OS/CPU. Java compiles to bytecode that any compliant JVM can run.
| Approach | Portability |
|---|---|
| C/C++ native binary | Tied to target OS/ABI—you rebuild per platform |
| Java bytecode + JVM | Same .class / JAR can run anywhere a JVM exists |
Trade-off: you depend on a JVM runtime and accept some startup/warmup cost in exchange for portability and a rich standard library.
A strong answer is:
Java targets the JVM with bytecode, not a specific CPU/OS binary. That portability is the platform difference—one build artifact runs on any machine with a compatible JVM.
Why people say that Java is 'write once and run anywhere' language?
The slogan refers to bytecode portability, not magic immunity from platform differences.
How it works:
- You write
.javasource once. javaccompiles to bytecode (.class).- Any JVM on Linux, Windows, or macOS can load and run that bytecode.
Caveats interviewers like to hear:
- File paths, line endings, and native libraries still differ by OS.
- You still test on target platforms for I/O, networking, and JNI.
- JVM version matters—bytecode targets a class file version.
A strong answer is:
Write once, run anywhere means bytecode runs on any JVM. I still validate on target platforms because filesystem, native libs, and JVM version can change behavior.
How does ClassLoader work in Java?
Class loaders find bytecode (classpath, modules, JARs) and define Class objects in the JVM. Loading is usually lazy—classes load when first referenced.
Three classic loaders (parent-delegation model):
| Loader | Loads |
|---|---|
| Bootstrap | Core JDK classes (java.*) from rt / modules |
| Platform (Extension) | Extension libraries (jre/lib/ext legacy; modules in modern JDK) |
| Application (System) | Your classes and dependencies on the classpath / module path |
Delegation rule: A loader asks its parent first. This prevents you from replacing core java.lang.String with your own copy.
Interview follow-up: Custom class loaders appear in app servers, OSGi, and some serialization/security scenarios.
A strong answer is:
Class loaders load bytecode on demand using parent delegation—bootstrap for core JDK classes, application loader for my code on the classpath. I mention delegation when discussing class isolation in containers or plugins.
Language basics and main method
Do you think ‘main’ used for main method is a keyword in Java?
No. main is not a keyword—it is simply the method name the JVM launcher looks for when you run java MyClass.
You can define other methods named main in the same class (unusual but legal). What matters is the signature the launcher expects:
public static void main(String[] args)A strong answer is:
main is a convention enforced by the JVM launcher, not a Java keyword. The required signature is public, static, void, and accepts a String array.
Can we write main method as public void static instead of public static void?
No. Modifier order can vary (static public is fine), but return type must come after modifiers.
Valid:
public static void main(String[] args) { }
static public void main(String[] args) { }Invalid:
public void static main(String[] args) { } // compile errorA strong answer is:
Modifiers can be reordered, but return type follows modifiers. public void static is illegal because void ends up in the wrong position.
In Java, if we do not specify any value for local variables, then what will be the default value of the local variables?
Local variables have no default value. If you declare a local variable and use it before assigning, the compiler reports an error—not a null at runtime.
void demo() {
int count;
// System.out.println(count); // compile error: variable count might not have been initialized
}Contrast with fields (instance/static variables): Those get default values (0, false, null).
This distinction trips people up in interviews—always separate locals from fields.
A strong answer is:
Locals must be assigned before use; the compiler enforces that. Only fields get default initialization—null for references, zero for numbers, false for booleans.
Let say, we run a java class without passing any arguments. What will be the value of String array of arguments in Main method?
When you run java MyApp with no args, args is a zero-length array, not null.
public static void main(String[] args) {
System.out.println(args.length); // 0
System.out.println(args == null); // false
}Safe pattern: iterate args without a null check; length 0 means no arguments.
A strong answer is:
args is an empty String array with length 0, never null. I can loop over args directly when parsing CLI flags.
What is the difference between byte and char data types in Java?
Both are integral types, but they represent different things.
| Type | Size | Range / role |
|---|---|---|
byte |
8 bits | -128 to 127 — raw binary numeric data |
char |
16 bits | UTF-16 code unit — character/text data ('A', '\u0041') |
Interview note: char is unsigned (0–65535). byte is signed. Neither is for everyday text processing—use String for that.
A strong answer is:
byte is an 8-bit signed integer; char is a 16-bit UTF-16 character. I use String for text and byte[] for raw binary data.
OOP principles and inheritance
What are the main principles of Object Oriented Programming?
The four pillars interviewers expect you to name and apply, not just list:
| Principle | One-line meaning | Interview signal |
|---|---|---|
| Encapsulation | Hide internal state; expose behavior via methods | Private fields + getters/setters, invariants |
| Abstraction | Show essential behavior, hide complexity | Interfaces, abstract classes, service APIs |
| Inheritance | Reuse and extend behavior (IS-A) |
Parent/child classes—use sparingly |
| Polymorphism | Same interface, different implementations | Overriding, interface types |
A strong answer is:
I name all four, then give a concrete example—encapsulation with private fields, polymorphism with an interface type holding different implementations.
What is the difference between Object Oriented Programming language and Object Based Programming language?
| OOP language (Java, C++) | Object-based (JavaScript historically, VBScript) | |
|---|---|---|
| Inheritance | Class-based inheritance supported | Often prototype-based; limited class inheritance |
| Polymorphism | Full compile-time + runtime polymorphism | More dynamic; patterns differ |
| Encapsulation | Strong with classes, access modifiers | Possible with objects/closures |
Modern JavaScript has classes, but Java interviews still use this question to check whether you understand full OOP vs "objects without a rigid class model."
A strong answer is:
OOP languages like Java support class inheritance and polymorphism as first-class features. Object-based languages may have objects and encapsulation but weaker or different inheritance models.
Why do we need constructor in Java?
A constructor initializes a new object's state when new runs. It has the same name as the class and no return type.
Why it matters:
- Sets required fields and invariants before other methods run
- Can overload constructors for different creation paths
- Can call
this(...)orsuper(...)to chain setup
Default constructor: If you define no constructors, Java provides a public no-arg constructor. If you add any constructor, the default is not generated—you must define no-arg explicitly if callers need it.
A strong answer is:
Constructors initialize object state at creation time. I remember that adding any custom constructor removes the implicit default unless I declare one myself.
Explain the concept of Inheritance?
Inheritance lets a child class reuse and extend a parent class—an IS-A relationship (Dog extends Animal).
Benefits:
- Code reuse for shared behavior
- Polymorphism—treat child as parent type
- Method overriding for specialized behavior
Risks (mention in experienced loops):
- Fragile base class—parent changes break children
- Deep hierarchies hurt readability
- Prefer composition when behavior is "HAS-A" not "IS-A"
A strong answer is:
Inheritance models IS-A relationships for reuse and polymorphism. I also mention composition when the relationship is really HAS-A or when hierarchies would get deep.
Why Java does not support multiple inheritance?
Java allows a class to extend only one superclass. Multiple inheritance of classes was omitted to avoid the diamond problem: if two parents implement the same method differently, which version does the child inherit?
Classic ambiguity example: Class C extends A, B and both A and B define foo()—the compiler cannot pick a single override.
What Java allows instead:
- A class implements multiple interfaces
- Default methods on interfaces (Java 8+) with explicit conflict resolution rules
A strong answer is:
Java avoids multiple class inheritance because of diamond ambiguity. I use interfaces—and default methods when needed—to combine multiple contracts without inheriting conflicting class implementations.
How aggregation and composition are different concepts?
Both are HAS-A associations; strength of ownership differs.
| Relationship | Lifetime | Example |
|---|---|---|
| Composition | Strong—part dies with whole | Car has Engine; no car means no car-engine |
| Aggregation | Weak—parts can outlive container | University has Student; student exists without university |
Interview tip: Composition supports encapsulation—you control how internal parts are created and exposed.
A strong answer is:
Composition is strong ownership—the part cannot exist without the whole. Aggregation is weaker—the contained object can outlive the container. I pick composition when lifecycle must be tied together.
Constructors, this, and super
Why do we need default constructor in Java classes?
The default constructor is the no-argument constructor Java generates when you define no constructors at all.
Rules to remember:
| Situation | What Java does |
|---|---|
| No constructors written | Compiler adds public ClassName() { } |
| Any constructor written | Default is not generated—you must add no-arg yourself if needed |
| Subclass with no constructors | Compiler adds default that calls super() on parent |
Why it matters in interviews:
- Frameworks (JPA, Jackson, Spring) often need a no-arg constructor to create instances via reflection.
- If you only define
Person(String name), callers cannot writenew Person()unless you add an explicit no-arg constructor.
public class Person {
private String name;
public Person(String name) { this.name = name; }
// No default constructor — new Person() will not compile
}A strong answer is:
Java supplies a public no-arg constructor only when I define none. The moment I add any constructor, I must declare a no-arg one myself if frameworks or callers need it.
Why constructors cannot be final, static, or abstract in Java?
Constructors are special instance-initialization methods. Three modifiers are illegal for different reasons:
| Modifier | Why it is illegal |
|---|---|
| final | Constructors are not inherited or overridden—final adds nothing |
| abstract | Abstract means "no body"; every constructor must have a body to run when new executes |
| static | Static belongs to the class; constructors exist to initialize a specific new object |
// All compile errors:
// public final MyClass() { }
// public abstract MyClass();
// public static MyClass() { }A strong answer is:
Constructors initialize instances at
newtime—they need a body, cannot be class-level static methods, and are never overridden so final is meaningless.
What is the purpose of 'this' keyword in java?
this refers to the current object instance—the one whose method or constructor is running.
Common uses:
| Use | Example |
|---|---|
| Disambiguate fields from parameters | this.name = name; |
| Constructor chaining | this(otherArg) must be first statement |
| Pass current object | registerListener(this); |
| Call overridden method on current class | this.print() (not super) |
public class Account {
private final String id;
public Account(String id) {
this.id = id; // field vs parameter
}
public Account() {
this("default"); // chain to other constructor
}
}A strong answer is:
this is the current instance—I use it to resolve name clashes, chain constructors, or pass the object to another method. In an override scenario, this calls the child's version; super calls the parent's.
What is the purpose of 'super' keyword in java?
super refers to the immediate parent class from a child class method or constructor.
Two main jobs:
super(...)— call a parent constructor (must be first statement if used).super.method()— invoke an overridden parent method from the child.
public class Dog extends Animal {
public Dog(String name) {
super(name); // parent constructor
}
@Override
public void speak() {
super.speak(); // parent behavior, then extend
System.out.println("Woof");
}
}Note: If you omit super() in a child constructor, Java inserts a call to the parent's no-arg constructor automatically.
A strong answer is:
super reaches into the parent—either to run its constructor with super(...) or to call an overridden method with super.method(). I use it when the child extends rather than replaces parent behavior.
Is it possible to use this() and super() both in same constructor?
No. A constructor may call either this(...) or super(...) as its first statement—not both in the same constructor.
Why: Both delegate object setup to another constructor. The JVM must pick one path before any other statements run.
public class Child extends Parent {
public Child() {
super(1); // OK — first statement
// this(2); // compile error if super() already used
}
public Child(int x) {
this(); // chains to no-arg constructor above
}
}Chaining can still reach both parent and child logic indirectly: this() → another constructor → super().
A strong answer is:
this() and super() cannot appear together in one constructor because only one can be the first statement. I chain through another constructor if I need both parent and child setup paths.
Memory model and references
Why there are no pointers in Java?
Java exposes object references, not raw memory addresses you can arithmetic on.
What you get instead of C-style pointers:
| Pointer feature | Java equivalent |
|---|---|
| Address arithmetic | Not available |
Manual free() |
Garbage collector reclaims unreachable objects |
| Dereference any address | Only through typed references |
| Move objects in memory | JVM may relocate objects; references stay valid |
Benefits: Safer code, simpler memory management and garbage collection, and fewer segfault-class bugs.
String s = new String("hi"); // s is a reference, not an address you can increment
// s++; // not legalA strong answer is:
Java gives me references to objects, not manipulable pointers. The JVM owns memory layout and GC, which trades low-level control for safety and portability.
If there are no pointers in Java, then why do we get NullPointerException?
Programmers work with references; the JVM still uses pointers internally. A reference is either:
- Non-null — points at a live object (or array).
null— points at nothing.
NullPointerException (NPE) fires when you dereference a null reference—calling a method, reading a field, or indexing as if an object exists.
String s = null;
int len = s.length(); // NPE — no object behind the reference
Person p = getPerson(); // might return null from a DAO
p.getName(); // classic production NPEInterview follow-up: Use Optional, null checks, or validation at API boundaries to avoid NPEs in production.
A strong answer is:
References are the programmer-facing view of object locations. NPE means I tried to use a reference that points to no object—null is a valid reference value, but you cannot call methods on it.
What is the meaning of object cloning in Java?
Cloning creates a new object copy from an existing one. The standard hook is Object.clone(), which performs a shallow copy by default.
| Aspect | Detail |
|---|---|
| Shallow clone | Copies field values; reference fields still point to same nested objects |
| Deep clone | Nested objects copied too—usually custom logic or serialization |
| Contract | Class should implement Cloneable; override clone() and call super.clone() |
| Return type | Object.clone() returns Object—cast or override with covariant return |
public class Employee implements Cloneable {
private String name;
private int[] scores;
@Override
public Employee clone() throws CloneNotSupportedException {
Employee copy = (Employee) super.clone(); // shallow
copy.scores = scores.clone(); // deep-copy array
return copy;
}
}Modern alternative: Copy constructors or factory methods are often clearer than Cloneable.
A strong answer is:
Cloning duplicates an object; default clone() is shallow. For interview depth I mention deep vs shallow copy and that copy constructors are often preferable to Cloneable.
Static members and initialization
In Java, why do we use static variable?
A static variable belongs to the class, not to any single instance. All objects share one copy.
When to use:
| Use case | Example |
|---|---|
| Shared configuration | MAX_CONNECTIONS |
| Counters across instances | totalInstancesCreated |
| Constants | public static final int DEFAULT_PORT = 8080 |
public class ConnectionPool {
private static int activeCount = 0; // one value for entire JVM class
public ConnectionPool() {
activeCount++;
}
}Memory note: Static fields live for the class loader's lifetime (often application lifetime), not per object.
A strong answer is:
Static variables hold class-wide state shared by every instance. I use them for constants and true shared counters—not for per-object data that should stay encapsulated.
Why it is not a good practice to create static variables in Java?
Mutable static state is a common source of bugs, tight coupling, and test pain.
Problems:
| Issue | Why it hurts |
|---|---|
| Global mutable state | Any code can change it—hard to reason about order of updates |
| Thread safety | Shared writes need synchronization or atomics |
| Testing | Tests leak state unless you reset static fields between runs |
| Hidden dependencies | Instance methods secretly depend on class-level globals |
| OOP friction | Behavior tied to class instead of object lifecycle |
Better patterns: Inject dependencies, use instance fields, or confine mutable state to well-defined singletons with clear lifecycle.
A strong answer is:
Static mutable variables are global variables in disguise. I avoid them unless the value is truly constant or I have a deliberate, thread-safe singleton design.
What is the purpose of static method in Java?
A static method belongs to the class. You call it on the class name without creating an instance.
Good fits:
- Utility functions (
Math.max,Collections.sort) - Factory methods (
Optional.of,List.of) - Behavior that does not need instance fields
public class StringUtils {
public static boolean isBlank(String s) {
return s == null || s.trim().isEmpty();
}
}
// StringUtils.isBlank(" "); — no object neededRestriction: Static methods can access only static members directly; instance fields require an object reference.
A strong answer is:
Static methods express class-level behavior that does not depend on a particular object's state. I keep them stateless utilities when possible.
Why do we mark main method as static in Java?
The JVM launches your program before any object of your class exists. It needs an entry point it can call on the class, not on an instance.
public class App {
public static void main(String[] args) {
System.out.println("JVM calls this without new App()");
}
}If main were instance method: The launcher would need to know which constructor to use to create the first object—ambiguous and unnecessary.
A strong answer is:
main is static because the JVM starts execution without constructing an object. The launcher invokes App.main(args) on the class itself.
In what scenario do we use a static block?
A static initializer block runs once when the class is first loaded—before any static method or constructor on that class.
Use when:
- Static fields need non-trivial setup (read config, register drivers)
- One-time class-level registration
public class DbConfig {
private static final Properties props;
static {
props = new Properties();
try (var in = DbConfig.class.getResourceAsStream("/db.properties")) {
props.load(in);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
}Order: Static fields and static blocks run top-to-bottom, then the class is ready. Static blocks run before main.
A strong answer is:
Static blocks initialize complex class-level state once at class load time—things too heavy for a one-line field initializer.
What happens when static modifier is not mentioned in the signature of main method?
The JVM looks for:
public static void main(String[] args)| Scenario | Result |
|---|---|
public void main(String[] args) |
Compiles but fails at runtime |
Run with java MyClass |
NoSuchMethodError: main |
The launcher cannot call an instance method without first creating an object—and it does not create one for you.
A strong answer is:
Without static, main is just another instance method. The program may compile, but the JVM entry point is missing so you get NoSuchMethodError at launch.
What is the difference between static method and instance method in Java?
| Static method | Instance method | |
|---|---|---|
| Belongs to | Class | Specific object |
| Call syntax | ClassName.method() |
object.method() |
| Can use instance fields? | Only via an object reference | Yes, on this |
| Can use static fields? | Yes | Yes |
| Polymorphism | Resolved by reference type (hiding) | Resolved by runtime object type (overriding) |
public class Counter {
private int count = 0;
private static int total = 0;
public void increment() { count++; total++; } // instance
public static int getTotal() { return total; } // static — no this.count
}A strong answer is:
Static methods are class utilities; instance methods operate on object state. Static methods cannot touch instance fields without an object reference.
Are we allowed to override a static method in Java?
No. Static methods are not polymorphic in the override sense. A subclass method with the same signature hides the parent's static method—it does not override it.
class Parent {
public static void greet() { System.out.println("Parent"); }
}
class Child extends Parent {
public static void greet() { System.out.println("Child"); } // hiding, not overriding
}
Parent p = new Child();
p.greet(); // prints "Parent" — compile-time binding
Child.greet(); // prints "Child"Rule: @Override on a static method is a compile error. Instance methods use dynamic dispatch; static methods use static binding on the reference type.
A strong answer is:
You cannot override static methods—you can only hide them. Which method runs is chosen at compile time from the reference type, not the runtime object.
Polymorphism and binding
What is the difference between method overloading and method overriding in Java?
| Overloading | Overriding | |
|---|---|---|
| Where | Same class (or inherited + new overloads) | Parent and child in inheritance |
| Signature | Same name, different parameters | Same name and parameters |
| Binding | Compile time (static) | Runtime (dynamic) |
| Return type | Can differ independently | Covariant return allowed (subtype) |
| Access | Any visibility | Cannot reduce visibility |
// Overloading
void print(int x) { }
void print(String s) { }
// Overriding
class Animal { void speak() { } }
class Dog extends Animal { @Override void speak() { } }A strong answer is:
Overloading is same name, different parameters, resolved at compile time. Overriding is same signature in a subclass, resolved at runtime based on the actual object type.
What is meant by covariant return type in Java?
Since Java 5, an overriding method may return a narrower (subtype) return type than the parent method. That is a covariant return type.
class Animal {
Animal reproduce() { return new Animal(); }
}
class Dog extends Animal {
@Override
Dog reproduce() { return new Dog(); } // covariant — Dog is subtype of Animal
}Before Java 5: Override required the exact same return type.
Applies to: Reference return types in overrides—not primitives (you cannot covariant int to long in an override).
A strong answer is:
Covariant return lets a subclass override with a more specific return type—Dog instead of Animal—while keeping the same method signature otherwise.
What is Runtime Polymorphism?
Runtime polymorphism (dynamic polymorphism) means the JVM picks which overridden instance method to run based on the actual object type, not the reference type.
Animal a = new Dog();
a.speak(); // Dog.speak() runs at runtime
void process(Animal animal) {
animal.speak(); // could be Cat, Dog, etc.—resolved when call executes
}Requires: Inheritance + instance method override + assignment to a supertype reference.
Not runtime polymorphic: Static methods (hiding), fields (hidden not overridden), overloaded methods (compile-time choice).
A strong answer is:
Runtime polymorphism is dynamic dispatch on overridden instance methods—the JVM calls the version belonging to the real object, even when the variable is typed as the parent.
Explain the difference between static and dynamic binding?
Binding is when the JVM/compiler links a call site to the method implementation.
| Static binding | Dynamic binding | |
|---|---|---|
| When resolved | Compile time | Runtime |
| Applies to | Static methods, final methods, private methods, overloaded methods | Overridden instance methods |
| Decision based on | Reference type | Actual object type |
class A { void m() { } static void s() { } }
class B extends A { void m() { } static void s() { } }
A ref = new B();
ref.m(); // dynamic — B.m()
ref.s(); // static — A.s()Interview trap: Overloading is always static binding—the compiler picks the overload from argument types at compile time.
A strong answer is:
Static binding fixes the target at compile time—overloads, static methods, final methods. Dynamic binding defers overridden instance methods until runtime based on the real object.
Abstraction, interfaces, and annotations
What is Abstraction in Object Oriented programming?
Abstraction hides implementation complexity and exposes only what callers need.
In practice:
| Mechanism | What caller sees |
|---|---|
| Abstract class | Partial implementation + abstract hooks |
| Interface | Contract of operations |
| Public API | Methods on a concrete class; internals private |
// Caller knows pay() — not how card vs wallet differs
public interface PaymentGateway {
void pay(Money amount);
}Not the same as: abstract class keyword—that is one Java language tool for abstraction, not the OOP concept itself.
A strong answer is:
Abstraction is a design idea—show essential behavior, hide how it works. Interfaces and abstract classes are Java mechanisms that implement abstraction.
How is Abstraction different from Encapsulation?
Both reduce complexity, but at different angles:
| Abstraction | Encapsulation | |
|---|---|---|
| Focus | What to expose vs hide | Bundling data + behavior; guarding access |
| Level | Design / API shape | Implementation / access control |
| Typical tools | Interfaces, abstract classes, layering | private fields, getters/setters, immutability |
public class BankAccount {
private BigDecimal balance; // encapsulation — field hidden
public void deposit(BigDecimal amt) { /* rules inside */ } // abstracted operation
}Relationship: Good encapsulation supports abstraction—you cannot hide implementation without controlling access.
A strong answer is:
Abstraction is about the simplified view you offer. Encapsulation is about locking internal state behind controlled access—private fields and public methods.
What is an abstract class in Java?
An abstract class cannot be instantiated directly. It may declare abstract methods (no body) and provide concrete shared code for subclasses.
Rules:
| Rule | Detail |
|---|---|
| Instantiation | new AbstractClass() is illegal |
| Subclass duty | Non-abstract child must implement all abstract methods |
| Abstract method | No body; child provides implementation |
| Can have | Fields, constructors, concrete methods |
public abstract class Shape {
protected String color;
public abstract double area(); // subclass must implement
public String getColor() { return color; } // shared concrete code
}A strong answer is:
An abstract class is a partial base—you cannot new it, but subclasses inherit shared code and must fill in abstract methods.
Is it allowed to mark a method abstract as well as final?
No. The modifiers contradict each other.
| Modifier | Meaning |
|---|---|
| abstract | Subclass must provide implementation |
| final | Subclass cannot override |
// public abstract final void draw(); // compile errorSame logic applies to abstract static or abstract private (in older Java)—abstract methods must be overridable by subclasses.
A strong answer is:
abstract means "subclass implements me"; final means "nobody overrides me." A method cannot be both.
How Annotations are better than Marker Interfaces?
Marker interfaces (e.g., Serializable) tag a type with no methods—metadata encoded only as "implements X."
Annotations carry richer, flexible metadata:
| Feature | Marker interface | Annotation |
|---|---|---|
| Data payload | None | Attributes (@RequestMapping("/api")) |
| Target | Types only | Methods, fields, parameters, etc. |
| Retention policy | Always on type | SOURCE / CLASS / RUNTIME |
| Tooling | instanceof checks |
Reflection, bytecode processors, frameworks |
@Deprecated
@SuppressWarnings("unchecked")
@Entity
public class User { }Trade-off: Marker interfaces are visible in type signatures; annotations can be quieter but depend on runtime scanning.
A strong answer is:
Annotations beat marker interfaces when I need configurable metadata on methods or fields, retention control, and framework processing—not just a type tag with no data.
What is the difference between abstract class and interface in Java?
| Abstract class | Interface | |
|---|---|---|
| Inheritance | extends one class |
implements multiple interfaces |
| State | Instance fields allowed | Only public static final constants |
| Constructors | Yes | No |
| Method bodies | Concrete + abstract methods | Abstract (implicit), default, static (Java 8+) |
| Best for | Shared base implementation | Cross-cutting contracts |
Modern Java (8+): Interfaces can have default and static methods—so "only abstract methods" is outdated for interviews.
Design heuristic:
- IS-A with shared code → abstract class
- CAN-DO capability → interface (
Comparable,Runnable)
A strong answer is:
Abstract classes anchor a family with shared state and constructors. Interfaces define capabilities you can mix in—multiple per class—with defaults for optional behavior since Java 8.
How can we cast to an object reference to an interface reference?
If a class implements an interface, every instance is-a implementor of that interface. You can assign or cast to the interface type without changing the object—only the compile-time view.
class ArrayList<E> implements List<E> { /* ... */ }
List<String> list = new ArrayList<>(); // widening to interface — preferred
ArrayList<String> arr = new ArrayList<>();
List<String> view = (List<String>) arr; // explicit cast — usually redundant hereRules:
- Upcast (class → interface it implements): always safe, often implicit.
- Downcast (interface → concrete class): needs
instanceofcheck or you riskClassCastException.
void process(List<String> list) {
if (list instanceof ArrayList<String> al) {
al.trimToSize(); // safe downcast
}
}A strong answer is:
Any object whose class implements an interface can be referenced through that interface. Upcast is automatic; downcast to a concrete class requires that the object actually is that type.
Packages and core classes
What is the purpose of package in Java?
A package groups related types and controls naming and visibility.
Why packages matter:
| Purpose | Benefit |
|---|---|
| Organization | com.app.service, com.app.model mirror domain structure |
| Name uniqueness | Two User classes can coexist in different packages |
| Access control | Package-private (default) scope limits cross-package access |
| Encapsulation | Hide implementation packages from public API surface |
package com.example.billing;
import com.example.billing.model.Invoice;
public class BillingService { }Convention: Reverse DNS (com.company.product) avoids global name clashes.
A strong answer is:
Packages namespace and organize code, prevent class name collisions, and enforce access boundaries—not just folder structure.
What is java.lang package?
java.lang is imported implicitly into every compilation unit. It holds core language types.
Notable classes:
| Class | Role |
|---|---|
Object |
Root of all classes |
String, StringBuilder |
Text |
Integer, Long, Boolean, … |
Wrapper types |
Math |
Numeric helpers |
System |
out, err, gc(), currentTimeMillis() |
Throwable, Exception, Error |
Exception hierarchy |
Class, Runtime |
Reflection and runtime |
You never need import java.lang.Object;—it is always available.
A strong answer is:
java.lang is the automatic core package—Object, String, wrappers, System, and the exception hierarchy. Every Java file sees it without an explicit import.
Which is the most important class in Java?
Open-ended—but java.lang.Object is the standard strong answer.
Why Object matters:
| Feature | Impact |
|---|---|
| Root of class hierarchy | Every class extends Object (directly or indirectly) |
equals / hashCode |
Collection correctness |
toString |
Logging and debugging |
getClass |
Reflection entry point |
wait / notify |
Intrinsic locking (legacy coordination) |
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person other)) return false;
return Objects.equals(id, other.id);
}Alternate answers (if you justify them): String for immutability interviews, Class for reflection-heavy roles.
A strong answer is:
Object is the root of every class and defines equals, hashCode, and toString contracts that ripple through collections and debugging—I treat it as the most foundational class.
Can you import same package or class twice in your class?
Duplicate imports are harmless. The compiler collapses them—no error, no extra bytecode.
import java.util.List;
import java.util.List; // redundant but legal| Scenario | Result |
|---|---|
| Same import twice | Ignored silently |
| Same class loaded at runtime | Class loader loads once per loader |
| Two classes, same simple name | Compile error unless you use fully qualified name for one |
import java.util.Date;
// import java.sql.Date; // clash — use FQCN for one of themPart two: Continue with Java Interview Questions and Answers — Part 2 for collections, garbage collection, exceptions, threading, and Java 8+ features.
A strong answer is:
Importing the same type twice is a no-op. Real problems come from simple-name collisions between two different classes with the same short name.
Concurrency preview
What is a Thread in Java?
A thread is a lightweight unit of execution within a process. Multiple threads share the process heap but each has its own stack and program counter.
Basics:
| Concept | Detail |
|---|---|
| vs process | Threads share memory; processes are isolated |
| Java model | java.lang.Thread or executor frameworks |
| Default | JVM starts one thread to run main |
| Concurrency goal | Overlap I/O or parallelize CPU work (with care) |
Thread t = new Thread(() -> System.out.println("Running in worker"));
t.start(); // async — does not block caller after start()
// Prefer executors in production:
ExecutorService pool = Executors.newFixedThreadPool(4);Preview only here: Thread lifecycle, synchronization, and java.util.concurrent are covered in part two.
A strong answer is:
A thread is an independent execution path inside the JVM process—main is one thread; I create more for concurrent work, with shared heap and per-thread stacks.

