Object-Oriented Programming (OOP) is a fundamental programming paradigm that is essential for many modern programming languages. Below are over 30 commonly asked OOP interview questions along with detailed answers to help you prepare effectively.
OOP Interview Questions and Answers
- What is Object-Oriented Programming (OOP)?
- What are the main features of OOP?
- What is a class?
- What is an object?
- Explain inheritance with an example.
- What is polymorphism?
- What is encapsulation? Give an example.
- What is abstraction in OOP? How can we achieve it?
- Can you explain method overloading vs method overriding?
- What are access modifiers in OOP?
- What is constructor chaining?
- What are interfaces in OOP?
- Explain multiple inheritance in OOP. Is it supported?
- What do you understand about static polymorphism?
- Can you explain dynamic polymorphism?
- What are abstract classes? How do they differ from interfaces?
- Explain garbage collection in OOP languages like Java.
- What do you understand about copy constructors?
- Can you explain what operator overloading means?
- What do you understand about final variables in Java?
- What is the difference between an abstract class and a concrete class?
- What is the significance of the super keyword in Java?
- What is method overriding? How does it work?
- What is an interface? How does it differ from an abstract class?
- What do you understand by encapsulation? Why is it important?
- What are constructors in OOP? Explain their types.
- What do you understand about static variables and methods?
- Can you explain what composition means in OOP?
- What do you mean by aggregation in OOP? How does it differ from composition?
- Explain what design patterns are in OOP with examples.
1. What is Object-Oriented Programming (OOP)?
Object-Oriented Programming (OOP) is a programming paradigm that uses “objects” to represent data and methods. An object is an instance of a class, which serves as a blueprint for creating objects. OOP focuses on the following key principles:
- Encapsulation: Bundling the data (attributes) and methods (functions) that operate on the data into a single unit called a class.
- Inheritance: Allowing one class to inherit properties and behaviors from another class, promoting code reusability.
- Polymorphism: Enabling methods to do different things based on the object it is acting upon, often through method overriding or overloading.
- Abstraction: Hiding complex implementation details and showing only the essential features of an object.
These principles help in creating modular, reusable, and maintainable code.
2. What are the main features of OOP?
The main features of OOP include:
- Encapsulation: Protects the internal state of an object from unintended interference and misuse by restricting access to some of the object’s components.
- Inheritance: Facilitates code reuse by allowing new classes to inherit properties and methods from existing classes.
- Polymorphism: Allows methods to be defined in multiple forms, enabling a single interface to represent different underlying forms (data types).
- Abstraction: Simplifies complex systems by modeling classes based on essential characteristics while hiding unnecessary details.
These features collectively enhance code organization and facilitate easier troubleshooting and maintenance.
3. What is a class?
A class is a user-defined blueprint or prototype from which objects are created. It defines a set of attributes (data members) and methods (functions) that the created objects will have. For example, consider a class Car
:
class Car {
String color;
String model;
void displayDetails() {
System.out.println("Model: " + model + ", Color: " + color);
}
}
In this example, Car
is a class with attributes color
and model
, and it has a method displayDetails()
that prints the car’s details.
4. What is an object?
An object is an instance of a class that contains both data and behavior defined by its class. Objects represent real-world entities, such as cars, dogs, or bank accounts. Each object has its own state represented by attributes and can perform actions defined by its methods. For example:
Car myCar = new Car();
myCar.color = "Red";
myCar.model = "Toyota";
myCar.displayDetails(); // Outputs: Model: Toyota, Color: Red
Here, myCar
is an object of the Car
class with specific values for its attributes.
5. Explain inheritance with an example.
Inheritance allows one class (child or subclass) to inherit fields and methods from another class (parent or superclass). This promotes code reusability and establishes a relationship between classes. For example:
class Vehicle {
void start() {
System.out.println("Vehicle started");
}
}
class Car extends Vehicle {
void honk() {
System.out.println("Car honks");
}
}
In this example, Car
inherits from Vehicle
, meaning it can use the start()
method defined in Vehicle
. Thus, when we create an object of Car
, it can call both start()
and honk()
:
Car myCar = new Car();
myCar.start(); // Outputs: Vehicle started
myCar.honk(); // Outputs: Car honks
6. What is polymorphism?
Polymorphism allows methods to perform different tasks based on the object invoking them. There are two types of polymorphism:
- Compile-time polymorphism (Method Overloading): Multiple methods can have the same name but different parameters within the same class.
- Runtime polymorphism (Method Overriding): A subclass can provide a specific implementation of a method already defined in its superclass.
Example of method overloading:
class MathOperations {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
Example of method overriding:
class Animal {
void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
}
In this case, calling sound()
on an instance of Dog
will invoke the overridden method.
7. What is encapsulation? Give an example.
Encapsulation is the concept of wrapping data (attributes) and methods (functions) into a single unit called a class while restricting access to some components. This helps protect the integrity of the data and prevents external interference.
Example:
class BankAccount {
private double balance;
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public double getBalance() {
return balance;
}
}
In this example, balance
is private; it cannot be accessed directly from outside the BankAccount
class. Instead, access is controlled through public methods like deposit()
and getBalance()
.
8. What is abstraction in OOP? How can we achieve it?
Abstraction in OOP refers to hiding complex implementation details while exposing only the necessary parts of an object’s functionality. This can be achieved through abstract classes or interfaces.
Example using an abstract class:
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() {
System.out.println("Drawing Circle");
}
}
In this case, Shape
provides an abstract method draw()
without implementing it, while Circle
provides its specific implementation.
9. Can you explain method overloading vs method overriding?
Method overloading occurs when multiple methods in the same class have the same name but different parameters (type or number). This allows for different implementations based on input types or counts.
Example of method overloading:
class Display {
void show(int num) {
System.out.println("Integer: " + num);
}
void show(String str) {
System.out.println("String: " + str);
}
}
Method overriding occurs when a subclass provides a specific implementation for a method already defined in its superclass. The overridden method must have the same name and parameter list as in the superclass.
Example of method overriding:
class Parent {
void display() {
System.out.println("Display Parent");
}
}
class Child extends Parent {
void display() {
System.out.println("Display Child");
}
}
In this case, when calling display()
on an instance of Child
, it will execute the overridden version from Child
.
10. What are access modifiers in OOP?
Access modifiers are keywords that set the accessibility levels for classes, methods, and variables. The common access modifiers are:
- Public: Accessible from any other class.
- Private: Accessible only within its own class.
- Protected: Accessible within its own package and by subclasses.
- Default (no modifier): Accessible only within its own package.
These modifiers help enforce encapsulation by controlling how entities interact with each other.
11. What is constructor chaining?
Constructor chaining refers to calling one constructor from another constructor within the same class or between base and derived classes using keywords like this()
or super()
. This allows for code reuse and initialization flexibility.
Example:
class Animal {
Animal() {
System.out.println("Animal created");
}
Animal(String name) {
this(); // Calls default constructor
System.out.println("Animal name: " + name);
}
}
In this example, creating an instance using new Animal("Dog")
invokes both constructors sequentially.
12. What are interfaces in OOP?
An interface in OOP is a reference type similar to a class that can contain only constants, method signatures, default methods, static methods, and nested types. Interfaces cannot contain instance fields or constructors; they define behaviors that implementing classes must fulfill.
Example:
interface Drawable {
void draw();
}
class Rectangle implements Drawable {
public void draw() {
System.out.println("Drawing Rectangle");
}
}
In this case, any class implementing Drawable
must provide an implementation for the draw()
method.
13. Explain multiple inheritance in OOP. Is it supported?
Multiple inheritance refers to a feature where a class can inherit from more than one superclass. While some languages like C++ support multiple inheritance directly, Java does not allow it through classes to avoid ambiguity issues but permits it through interfaces.
For example:
interface A { void methodA(); }
interface B { void methodB(); }
class C implements A, B {
public void methodA() { /* Implementation */ }
public void methodB() { /* Implementation */ }
}
Here, class C implements two interfaces A and B without any ambiguity regarding inherited methods.
14. What do you understand about static polymorphism?
Static polymorphism occurs at compile time when multiple methods with the same name exist but differ in parameter lists within the same scope—this is also known as method overloading.
Example:
class MathUtils {
int add(int x, int y) { return x + y; }
double add(double x, double y) { return x + y; }
}
In this case, which version of add() gets called depends on whether integer or double arguments are passed during compilation.
15. Can you explain dynamic polymorphism?
Dynamic polymorphism occurs at runtime when a call to an overridden method is resolved at runtime rather than compile time—this is primarily achieved through method overriding in inheritance hierarchies.
Example:
class Animal {
void sound() { System.out.println("Animal sound"); }
}
class Cat extends Animal {
void sound() { System.out.println("Meow"); }
}
Animal myCat = new Cat();
myCat.sound(); // Outputs: Meow
Here, even though myCat is declared as type Animal, it calls Cat’s overridden sound() method during execution based on its actual object type.
16. What are abstract classes? How do they differ from interfaces?
An abstract class can contain both abstract methods (without implementation) and concrete methods (with implementation), allowing for partial abstraction while providing shared functionality among subclasses.
Interfaces only declare methods without providing implementations; all implementing classes must provide their versions of these methods.
Key differences include:
Feature | Abstract Class | Interface |
---|---|---|
Can contain fields | Yes | No |
Can contain constructors | Yes | No |
Method implementation | Can have both abstract & concrete | Only abstract (prior to Java 8) |
Multiple inheritance | No | Yes |
This distinction helps developers choose between using abstract classes or interfaces based on their design needs.
17. Explain garbage collection in OOP languages like Java.
Garbage collection (GC) is an automatic memory management process where the runtime environment identifies objects that are no longer referenced or needed by applications and frees up memory resources associated with them. This helps prevent memory leaks and optimizes memory usage without requiring manual deallocation by developers.
Java uses several algorithms for garbage collection such as mark-and-sweep or generational garbage collection to efficiently manage memory allocation during program execution without impacting performance significantly.
18. What do you understand about copy constructors?
A copy constructor initializes an object using another object of the same class type as input parameter; it’s typically used for deep copying when objects contain references to dynamically allocated memory or other resources that need independent copies rather than shared references.
Example in C++:
class MyClass {
public:
int* ptr;
MyClass(int value) {
ptr = new int(value);
}
MyClass(const MyClass &obj) { // Copy constructor
ptr = new int(*obj.ptr);
}
~MyClass() { delete ptr; } // Destructor
};
In this case, using MyClass obj2(obj1); creates a new independent copy rather than sharing pointers between obj1 and obj2.
19. Can you explain what operator overloading means?
Operator overloading allows developers to redefine how operators work with user-defined types (classes). This enables intuitive usage of operators like + or * with objects similar to built-in types—improving code readability while maintaining functionality consistency across different data types.
Example in C++:
class ComplexNumber {
public:
float real;
float imag;
ComplexNumber operator+(const ComplexNumber &c) {
return ComplexNumber(real + c.real, imag + c.imag);
}
};
Here we redefine how ‘+’ operates between two instances of ComplexNumber so they can be added together naturally like primitive types would be used mathematically.
20. What do you understand about final variables in Java?
Final variables in Java are constants that cannot be changed once assigned; they enforce immutability within your codebase—making them crucial for defining constant values that should remain unchanged throughout program execution.
Example:
final int MAX_VALUE = 100;
// MAX_VALUE = 200; // This will cause compile-time error.
Using final ensures that critical constants maintain their intended values throughout application runtime.
These questions cover various aspects of Object-Oriented Programming concepts essential for interviews across many software development roles.
21. What is the difference between an abstract class and a concrete class?
An abstract class is a class that cannot be instantiated on its own and may contain abstract methods (methods without implementation) as well as concrete methods (methods with implementation). It serves as a blueprint for other classes, allowing them to inherit its properties and methods while enforcing certain behaviors.
A concrete class, on the other hand, is a fully defined class that can be instantiated to create objects. It provides implementations for all of its methods, including those inherited from abstract classes.
Key Differences:
- Instantiation: Abstract classes cannot be instantiated directly, while concrete classes can be instantiated.
- Method Implementation: Abstract classes can have both abstract and concrete methods, whereas concrete classes must implement all methods.
- Purpose: Abstract classes are used to define common behavior for subclasses, while concrete classes are used to create actual objects.
Example:
abstract class Animal {
abstract void sound(); // Abstract method
void eat() { // Concrete method
System.out.println("Eating...");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Bark");
}
}
In this example, Animal
is an abstract class that cannot be instantiated directly, while Dog
is a concrete class that provides an implementation of the sound()
method.
22. What is the significance of the super
keyword in Java?
The super
keyword in Java is used to refer to the immediate parent class of the current object. It serves several purposes:
- Accessing Parent Class Methods: It allows access to methods of the superclass that may have been overridden in the subclass.
- Accessing Parent Class Constructors: It can be used to call the constructor of the parent class from within the subclass constructor.
- Accessing Parent Class Variables: It can be used to differentiate between instance variables of the subclass and those of the superclass when they have the same name.
Example:
class Parent {
Parent() {
System.out.println("Parent Constructor");
}
void display() {
System.out.println("Display Parent");
}
}
class Child extends Parent {
Child() {
super(); // Calls Parent constructor
System.out.println("Child Constructor");
}
void display() {
super.display(); // Calls Parent display method
System.out.println("Display Child");
}
}
In this example, super()
calls the constructor of Parent
, and super.display()
calls the overridden method from Parent
.
23. What is method overriding? How does it work?
Method overriding occurs when a subclass provides a specific implementation for a method that is already defined in its superclass. The overridden method in the subclass must have the same name, return type, and parameters as in the superclass. This allows subclasses to provide their unique behavior while maintaining a consistent interface.
Key points about method overriding:
- The method in the subclass must have the same signature as in the superclass.
- The overridden method can be called using a reference of the superclass type pointing to an object of the subclass (dynamic method dispatch).
Example:
class Animal {
void sound() {
System.out.println("Animal makes sound");
}
}
class Cat extends Animal {
@Override
void sound() { // Overriding method
System.out.println("Meow");
}
}
Animal myCat = new Cat();
myCat.sound(); // Outputs: Meow
In this example, Cat
overrides the sound()
method from Animal
, allowing it to provide its specific implementation.
24. What is an interface? How does it differ from an abstract class?
An interface in Java is a reference type similar to a class that can contain only constants, method signatures (abstract methods), default methods, static methods, and nested types. Interfaces are used to define a contract for what a class can do without specifying how it does it.
Key Differences Between Interface and Abstract Class:
- Method Implementation: Interfaces cannot have any concrete methods (prior to Java 8) except for default and static methods. Abstract classes can have both abstract and concrete methods.
- Multiple Inheritance: A class can implement multiple interfaces but can inherit from only one abstract class. This allows for greater flexibility with interfaces.
- Fields: Interfaces can only contain static final fields (constants), while abstract classes can have instance variables.
Example:
interface Drawable {
void draw(); // Abstract method
}
class Circle implements Drawable {
public void draw() {
System.out.println("Drawing Circle");
}
}
In this example, Drawable
defines an interface with an abstract method draw()
, which is implemented by the Circle
class.
25. What do you understand by encapsulation? Why is it important?
Encapsulation is one of the fundamental principles of OOP that involves bundling data (attributes) and methods (functions) that operate on that data into a single unit called a class. It restricts direct access to some components of an object and protects object integrity by preventing unintended interference and misuse.
Importance of Encapsulation:
- Data Hiding: By restricting access to certain attributes or methods, encapsulation helps protect sensitive data from unauthorized access or modification.
- Modularity: Encapsulated code is easier to maintain and modify since changes made within a class do not affect other parts of the program that use it.
- Improved Code Readability: Encapsulation promotes clear separation between interface (public methods) and implementation (private data), enhancing code clarity.
Example:
class Account {
private double balance; // Private variable
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public double getBalance() {
return balance;
}
}
In this example, balance
is private, ensuring that it cannot be accessed directly from outside the Account
class. Instead, access is controlled through public methods like deposit()
and getBalance()
.
26. What are constructors in OOP? Explain their types.
Constructors are special methods invoked when an object is created. They initialize object attributes and allocate memory for them. Constructors have no return type and share their name with their class.
There are two main types of constructors:
- Default Constructor: A constructor with no parameters or one where all parameters have default values. It initializes attributes with default values.
- Parameterized Constructor: A constructor that takes arguments to initialize object attributes with specific values at creation time.
Example:
class Person {
String name;
// Default Constructor
Person() {
name = "Unknown";
}
// Parameterized Constructor
Person(String name) {
this.name = name;
}
}
In this example, Person
has both a default constructor initializing name
to “Unknown” and a parameterized constructor allowing custom initialization when creating an object.
27. What do you understand about static variables and methods?
Static variables and methods belong to the class rather than any specific instance of the class. They are shared among all instances of that class, meaning there is only one copy of each static variable or method regardless of how many objects are created.
Key characteristics:
- Static Variables: Also known as class variables; they retain their value across instances. They are initialized only once when the class is loaded into memory.
- Static Methods: Can be called without creating an instance of the class. They cannot access instance variables or instance methods directly since they do not belong to any specific object.
Example:
class Counter {
static int count = 0; // Static variable
Counter() {
count++; // Increment count for each new instance
}
static void displayCount() { // Static method
System.out.println("Count: " + count);
}
}
// Usage:
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter.displayCount(); // Outputs: Count: 2
In this example, every time a new instance of Counter
is created, count
increments by one. The static method displayCount()
accesses this shared variable across all instances.
28. Can you explain what composition means in OOP?
Composition is a design principle in OOP where one class contains references to objects of other classes as part of its state or behavior. This relationship represents a “has-a” relationship between objects, allowing complex types to be built from simpler ones while promoting code reusability and modularity.
Composition differs from inheritance because it does not imply an “is-a” relationship but rather indicates ownership or containment.
Example:
class Engine {
void start() {
System.out.println("Engine started");
}
}
class Car {
private Engine engine; // Car has an Engine
Car() {
engine = new Engine();
}
void startCar() {
engine.start();
}
}
// Usage:
Car myCar = new Car();
myCar.startCar(); // Outputs: Engine started
In this example, Car
has an instance of Engine
, demonstrating composition where Car
relies on Engine
for functionality without inheriting from it.
29. What do you mean by aggregation in OOP? How does it differ from composition?
Aggregation is another design principle in OOP similar to composition but represents a weaker relationship between objects. In aggregation, one class contains references to objects of another class but does not own them; thus, these objects can exist independently outside their containing class. This relationship represents a “whole-part” relationship where parts can exist without being tied exclusively to their whole.
The key difference between aggregation and composition lies in ownership:
- Composition implies ownership; if the containing object is destroyed, so are its contained objects.
- Aggregation implies association; contained objects can exist independently even if their container is destroyed.
Example:
class Department {
String name;
Department(String name) {
this.name = name;
}
}
class University {
private List<Department> departments; // University has Departments
University() {
departments = new ArrayList<>();
}
void addDepartment(Department department) {
departments.add(department);
}
}
// Usage:
Department cs = new Department("Computer Science");
University uni = new University();
uni.addDepartment(cs); // Department exists independently of University
In this example, while University
contains references to multiple departments through aggregation, those departments can exist independently without being tied exclusively to any university instance.
30. Explain what design patterns are in OOP with examples.
Design patterns are reusable solutions or templates for commonly occurring problems within software design. They provide best practices for solving specific design issues while promoting code readability, maintainability, and flexibility across applications.
Some common types include:
- Creational Patterns: Deal with object creation mechanisms.
- Example: Singleton Pattern ensures only one instance of a class exists throughout application execution.
class Singleton {
private static Singleton instance;
private Singleton() {} // Private constructor
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- Structural Patterns: Focus on how classes and objects are composed.
- Example: Adapter Pattern allows incompatible interfaces to work together.
interface Target {
void request();
}
class Adaptee {
void specificRequest() { /*...*/ }
}
class Adapter implements Target {
private Adaptee adaptee;
Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
- Behavioral Patterns: Concerned with communication between objects.
- Example: Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified.
interface Observer {
void update();
}
class Subject {
private List<Observer> observers = new ArrayList<>();
void attach(Observer observer) { observers.add(observer); }
void notifyObservers() { observers.forEach(Observer::update); }
}
These design patterns help developers create scalable software systems by providing proven solutions tailored for various scenarios encountered during software development.
Learn More: Carrer Guidance
React JS Interview Questions with Detailed Answers for Freshers
Cypress Interview Questions with Detailed Answers
PySpark interview questions and answers
Salesforce admin interview questions and answers for experienced
Salesforce admin interview questions and answers for freshers
EPAM Systems Senior Java Developer Interview questions with answers
Flutter Interview Questions and Answers for all levels
Most common data structures and algorithms asked in Optum interviews