Core Java and OOP Basics
20 questions
1. What are the main features of Java? Explain "Write Once, Run Anywhere."
Java is known for object-oriented design, platform independence, strong memory management, automatic garbage collection, rich standard libraries, multithreading support, and a mature runtime ecosystem. It was designed to make large applications easier to build and maintain across different environments.
"Write Once, Run Anywhere" means Java source code is compiled into bytecode, not directly into machine-specific instructions. That bytecode runs on the JVM, so the same compiled program can run on Windows, Linux, or macOS as long as a compatible JVM is installed. The operating system changes, but the application binary usually does not.
2. What is the difference between JDK, JRE, and JVM?
JVM is the runtime engine that executes Java bytecode. It is responsible for class loading, memory management, bytecode execution, and garbage collection. JRE includes the JVM plus the standard libraries and runtime components needed to run Java applications.JDK is the full development kit. It contains the JRE along with developer tools such as javac, javadoc, and debugging utilities. A simple way to explain it in an interview is: JVM runs code, JRE provides the runtime environment, and JDK provides everything required to develop, compile, and run Java applications.
| Aspect | JVM | JRE | JDK |
|---|---|---|---|
| Purpose | Executes bytecode | Runs Java applications | Develops and runs Java applications |
| Contains | Execution engine | JVM plus core libraries | JRE plus development tools |
| Used By | Runtime only | Application users | Developers |
| Examples | Memory, GC, class loading | java command runtime | javac, javadoc, jar |
3. What is a platform-independent language? How does Java achieve it?
A platform-independent language allows the same program logic to run on different operating systems or hardware platforms without rewriting the source code for each one. The main goal is portability with minimal platform-specific changes.
Java achieves this by compiling source code into bytecode. That bytecode is executed by the JVM, which acts as an abstraction layer between the program and the operating system. Each platform provides its own JVM implementation, so the application stays the same while the runtime adapts to the local machine.
4. Explain the four pillars of OOP: Abstraction, Encapsulation, Inheritance, and Polymorphism.
Abstraction means exposing only the essential behavior of an object while hiding unnecessary implementation details. For example, a List interface exposes an add() method without revealing whether it uses an array or linked nodes internally.
Encapsulation means bundling data and behavior together and controlling access through methods instead of letting outside code change state freely. For example, keeping a bank account balance private and only allowing updates through a deposit() method that validates the amount.
Inheritance allows one class to reuse and extend behavior from another class, which helps model shared characteristics. For example, a Manager class can extend an Employee class to automatically inherit fields like name and methods like getSalary().
Polymorphism allows the same method call to behave differently depending on the actual object type. For example, calling draw() on a generic Shape reference might draw a Circle or a Square depending on the specific object it points to at runtime.
A practical way to summarize them is: abstraction defines what a component does, encapsulation protects how it works, inheritance enables reuse, and polymorphism allows flexible substitution.
5. What is the difference between == and .equals()?
== compares references for objects, which means it checks whether two variables point to the exact same object in memory. For primitive types, == compares actual values. .equals() is meant for logical equality and is often overridden by classes such as String, Integer, or domain models to compare meaningful content instead of identity.
This matters a lot in collections and business logic. Two different String objects can have the same text, so .equals() returns true even though == may return false. The simplest distinction is that == checks identity for objects, while .equals() checks logical equality.
| Aspect | == | .equals() |
|---|---|---|
| Objects | Reference comparison | Logical/content comparison |
| Primitives | Value comparison | Not applicable |
| Override Needed | No | Often overridden |
| Typical Risk | Wrong equality checks for objects | Incorrect behavior if implemented badly |
6. What are access modifiers in Java? Explain their scope.
Access modifiers control visibility of classes, fields, methods, and constructors. public makes a member accessible from anywhere. private restricts access to the same class only. protected allows access within the same package and also in subclasses outside the package. If no modifier is used, Java applies package-private access, which means visibility is limited to the same package.
The design goal is to use the smallest visibility needed, so internal state stays hidden and only intended behavior is exposed.
| Modifier | Same Class | Same Package | Subclass Outside Package | Anywhere |
|---|---|---|---|---|
private | Yes | No | No | No |
| Package-private | Yes | Yes | No | No |
protected | Yes | Yes | Yes | No |
public | Yes | Yes | Yes | Yes |
7. What is the difference between abstract class and interface?
An abstract class is used when related classes share state or partial implementation. It can have instance variables, constructors, concrete methods, and abstract methods. An interface defines a contract that classes agree to implement. Modern Java interfaces can also contain default and static methods, but they are still primarily about capability rather than shared state.
The real distinction is design intent. Use an abstract class when subclasses share common implementation or lifecycle behavior. Use an interface when unrelated classes should follow the same contract without being forced into one inheritance chain.
| Aspect | Abstract Class | Interface |
|---|---|---|
| State | Can hold instance state | Usually no instance state |
| Constructors | Yes | No |
| Inheritance | Single class inheritance only | Multiple interfaces allowed |
| Best Use | Shared base behavior | Behavior contract |
8. Can a class extend multiple classes? What about implementing interfaces?
A Java class cannot extend multiple classes because Java does not support multiple inheritance for classes. This avoids ambiguity problems such as two parent classes defining the same method or conflicting state handling.
A class can implement multiple interfaces. That is how Java supports multiple behavioral contracts without allowing multiple concrete base classes. In practice, a class usually extends one parent if it needs shared implementation, and it implements one or more interfaces when it needs to express capabilities such as Comparable, Runnable, or a custom service contract.
9. What is method overloading vs method overriding?
Method overloading means defining multiple methods with the same name in the same class but with different parameter lists. It is resolved at compile time and is a form of static polymorphism. Method overriding happens when a subclass provides its own implementation of a method already defined in the parent class, and that behavior is resolved at runtime.
The easiest way to explain the difference is that overloading changes how a method is called, while overriding changes how inherited behavior executes. One is about multiple signatures in the same type, and the other is about specialized behavior in a subtype.
| Aspect | Overloading | Overriding |
|---|---|---|
| Where | Same class | Subclass |
| Parameters | Must differ | Usually same signature |
| Binding | Compile-time | Runtime |
| Purpose | Convenience and API flexibility | Specialized inherited behavior |
10. Explain final, finally, and finalize().
final is a keyword used to restrict change. A final variable cannot be reassigned, a final method cannot be overridden, and a final class cannot be extended. finally is a block used with exception handling to run cleanup code whether an exception occurs or not.finalize() was a method that the garbage collector could call before reclaiming an object, but it is deprecated and should not be used for resource management because it is unpredictable and expensive. Modern Java uses try-with-resources and explicit cleanup instead of relying on finalize().
| Term | Type | Purpose |
|---|---|---|
final | Keyword | Restricts reassignment, overriding, or inheritance |
finally | Exception block | Runs cleanup logic |
finalize() | Method | Deprecated GC-related cleanup hook |
11. What is the difference between this and super?
this refers to the current object instance. It is used to access current fields, call current methods, or pass the current object around. It is also used in constructors through this(...) to call another constructor in the same class.super refers to the immediate parent class. It is used to access parent fields, call parent methods, or invoke the parent constructor through super(...). A simple way to explain it is: this means current object context, while super means parent class context.
12. What are constructors? Can a constructor be private?
A constructor is a special block used to initialize an object when it is created. It has the same name as the class and does not return any value, not even void. Constructors are commonly used to enforce valid initial state, inject dependencies, or set default values.
Yes, a constructor can be private. Private constructors are often used in utility classes, singleton patterns, and factory-based designs where object creation must be controlled. They matter when the class should decide how and when instances are created instead of allowing direct construction everywhere.
13. What is static keyword? Explain static variables, methods, and blocks.
The static keyword means the member belongs to the class itself rather than to individual objects. A static variable is shared across all instances, so there is one copy per class. A static method can be called without creating an object, but it cannot directly access non-static instance state.
A static block is executed once when the class is loaded and is typically used for class-level initialization. Static members are useful for shared configuration, utility functions, constants, counters, and one-time setup logic that should exist independently of any single object.
14. What is the default value of instance variables in Java?
Instance variables in Java automatically receive default values if they are not explicitly initialized. Numeric primitive types become 0 or their equivalent, boolean becomes false, char becomes the null character, and object references become null.
This rule applies to instance variables and static variables because they are part of class or object state managed by the JVM. It does not apply to local variables inside methods. Local variables must be assigned before use, otherwise compilation fails. The important distinction is between JVM-managed object state and method-local variables.
15. Explain the Java Memory Model (Stack vs Heap).
In a simple interview explanation, the stack stores method-level execution data such as local variables, method calls, and references for each thread. The heap stores objects and arrays that are created during program execution and can be shared through references.
The broader Java Memory Model is actually about how threads see reads and writes to shared memory, but interviewers often start with stack versus heap as the entry point. A safe answer is that stack memory is thread-specific and tied to call execution, while heap memory is where objects live and is managed by garbage collection.
16. What are wrapper classes? Why do we need them?
Wrapper classes are object representations of primitive types, such as Integer for int, Double for double, and Boolean for boolean. They allow primitive values to be treated as objects when the language or framework requires object behavior.
We need them because collections, generics, many utility APIs, and object-oriented operations work with objects, not primitives. Wrapper classes also provide useful helper methods for parsing, conversion, and comparison. Primitives are efficient for raw values, but wrappers are necessary when object semantics are required.
17. What is autoboxing and unboxing?
Autoboxing is the automatic conversion of a primitive type into its wrapper object, such as converting int to Integer. Unboxing is the reverse process, where Java converts a wrapper back into its primitive value when needed by an expression or assignment.
This feature reduces boilerplate, especially when working with collections, generics, and utility APIs that require objects instead of primitives. However, it can also introduce subtle issues such as NullPointerException when a null wrapper is unboxed, or unnecessary object creation in performance-sensitive code. The main trade-off is convenience versus hidden runtime cost.
18. What is the Object class? Name important methods.
Object is the root class of the Java class hierarchy, which means every Java class directly or indirectly inherits from it. Because of that, it defines the base behavior shared by all objects in the language.
Important methods include equals(), hashCode(), toString(), getClass(), clone(), wait(), notify(), and notifyAll(). The most important ones to explain are usually equals(), hashCode(), and toString() because they affect collection correctness, logging, debugging, and how domain objects behave in real applications. Concurrency-related methods like wait() and notify() are also part of that base contract.
19. What is the difference between String, StringBuilder, and StringBuffer?
String is immutable, so any modification creates a new object. StringBuilder is mutable and designed for efficient string changes in single-threaded code. StringBuffer is also mutable but synchronized, so it is thread-safe at the method level and usually slower than StringBuilder when that safety is unnecessary.
The practical answer is that String is best for fixed text or values passed around safely, StringBuilder is best for repeated concatenation in normal application code, and StringBuffer is mainly relevant when synchronized mutable string operations are specifically needed.
| Aspect | String | StringBuilder | StringBuffer |
|---|---|---|---|
| Mutability | Immutable | Mutable | Mutable |
| Thread Safety | Safe because immutable | Not synchronized | Synchronized |
| Performance for Repeated Changes | Lower | High | Lower than StringBuilder |
| Typical Use | Fixed text | Single-threaded concatenation | Legacy or thread-safe mutable text |
20. Why is String immutable in Java? What are its advantages?
String immutability means once a String object is created, its value cannot change. Java uses this design to improve safety, simplicity, and performance in several core areas of the platform.
Its advantages include thread safety without extra synchronization, safe use as map keys, reliable string pooling, and stronger security when values such as file paths, class names, or network addresses are passed between APIs. Because the content cannot change unexpectedly, one reference cannot silently affect another part of the program. That predictability is the main design benefit.