This 10 interview questions are frequently asked on interview board for freshers. Here all questions are explained in a easy way with example. Lets check it out–
1. What is Class?
In object-oriented programming (OOP), a class is a blueprint or a template for creating objects. It defines the structure and behavior that the objects created from the class will have. A class encapsulates data (attributes or properties) and methods (functions) that operate on that data. In other words, a class serves as a model for creating instances of objects with specific characteristics and behaviorst. It is a user defined type and acts like a blueprint.
2. What is Object?
In object-oriented programming, an object is a specific instance of a class. An object is a fundamental unit of code that represents a real-world entity, concept, or thing. An object is an instance of a class, which is a blueprint or template that defines the structure and behavior of the object. Objects are the building blocks of OOP and are used to model and interact with the world in software systems.
3. What is Constructor?
A constructor is a special type of method within a class that is automatically called when an object of the class is created. Its primary purpose is to initialize the attributes (properties) of the object to meaningful values and set up its initial state. Constructors ensure that an object is properly initialized and ready to be used immediately after its creation.
4. Which are the types of Constructor?
• Default Constructor : A default constructor is automatically provided by the compiler if a class doesn’t explicitly define any constructors. It has no parameters and initializes attributes to their default values (e.g., numeric attributes to 0, object references to null
). It’s used when an object is created without providing any specific initialization values.
public class MyClass { // Default constructor provided by the compiler }
• Parametrized Constructor : A parameterized constructor accepts one or more parameters, allowing you to pass specific values for attribute initialization during object creation. Parameterized constructors enable you to create objects with custom initializations.
public class Person { private String name; private int age; // Parameterized constructor public Person(String name, int age) { this.name = name; this.age = age; } }
• Copy Constructor : A copy constructor creates a new object by copying the attributes from an existing object of the same class. It’s useful when you want to create a new object with the same values as an existing one.
public class Student { private String name; private int age; // Copy constructor public Student(Student other) { this.name = other.name; this.age = other.age; } }
• Chained Constructors: Some programming languages allow constructors to be chained using the this()
keyword. This enables one constructor to call another constructor within the same class. This technique helps reduce code duplication when setting up object initialization.
public class Book { private String title; private String author; public Book(String title) { this(title, "Unknown"); } public Book(String title, String author) { this.title = title; this.author = author; } }
These are the primary types of constructors you’ll encounter in object-oriented programming. The choice of constructor type depends on the specific requirements of your class and how you want to initialize objects.
5. What is Constructor Overloading?
Constructor Overloading is a technique to create multiple constructors with different set of
parameters and different number of parameters. Like any other method, constructors can be overloaded. This means a class can have multiple constructors with different parameter lists. Overloading constructors allows you to provide various ways to initialize objects.
public class Rectangle { private double width; private double height; // Constructor with width and height public Rectangle(double width, double height) { this.width = width; this.height = height; } // Constructor with only width (assumes height is 1 by default) public Rectangle(double width) { this(width, 1.0); } }
6. What is Up-casting and Down-casting?
Upcasting:
Upcasting involves treating a derived (child) class object as an instance of its base (parent) class. In other words, you are moving up the class hierarchy. This is always safe and does not require an explicit type conversion. Upcasting is implicitly supported by the language and doesn’t involve any risk of data loss.
For example, consider a class hierarchy where Vehicle
is the base class and Car
is a derived class. You can upcast a Car
object to a Vehicle
object like this:
Vehicle vehicle = new Car(); // Upcasting
Here, the Car
object is treated as a Vehicle
object.
Downcasting:
Downcasting is the opposite of upcasting. It involves treating a base class object as an instance of its derived class. This is potentially risky because the base class object may not actually be an instance of the derived class, leading to runtime errors or unexpected behavior. Downcasting requires explicit type conversion using casting operators.
For example, let’s consider the same class hierarchy. You can downcast a Vehicle
object back to a Car
object like this:
Vehicle vehicle = new Car(); Car car = (Car) vehicle; // Downcasting
However, if the vehicle
object was not originally created as a Car
object, this downcast could lead to a ClassCastException
at runtime.
To avoid potential errors, you can use the instanceof
operator to check the compatibility before performing a downcast:
if (vehicle instanceof Car) { Car car = (Car) vehicle; // Downcasting } else { // Handle the case where the downcast is not possible }
In summary, upcasting involves treating a derived class object as a base class object, while downcasting involves treating a base class object as a derived class object. Upcasting is generally safe, while downcasting should be used cautiously and often requires checks to prevent runtime errors.
7. What is Association, Aggregation and Composition Relationship?
Association: Association represents a general relationship between classes. It signifies that objects of one class are related to objects of another class in some way. This relationship could be simple or complex. Associations can be bi-directional (both classes are aware of each other) or uni-directional (only one class is aware of the other).
For example, consider two classes: Student
and Teacher
. An association between them could represent the fact that a Student
is taught by a Teacher
, and a Teacher
teaches multiple Student
objects.
Aggregation: Aggregation is a specific type of association where one class represents a “whole” and another class represents a “part.” The part can exist independently of the whole. It’s a relationship where one class (the whole) contains or is composed of instances of another class (the part). Aggregation is often described using “has-a” relationships.
For example, consider a University
class and a Department
class. A University
can have multiple Department
objects. Even if a University
is deleted, the Department
objects can still exist independently.
Composition: Composition is a stronger form of aggregation. In composition, the part cannot exist without the whole. The lifetime of the part is controlled by the whole. If the whole is destroyed, the parts are also destroyed. Composition is used to model “part-of” relationships.
For example, consider a Car
class and a Wheel
class. A Car
is composed of multiple Wheel
objects. If the Car
is destroyed, the Wheel
objects associated with it are also destroyed.
In summary:
- Association: Represents a general relationship between classes.
- Aggregation: Represents a “whole-part” relationship, where parts can exist independently of the whole.
- Composition: Represents a stronger “whole-part” relationship, where parts cannot exist without the whole and are managed by the whole.
It’s important to understand and choose the appropriate type of relationship based on the real-world semantics you are trying to model in your software design.
8. Which are the principles of OOP?
Object-Oriented Programming (OOP) is a programming paradigm that focuses on organizing and structuring code around the concept of “objects,” which are instances of classes. OOP is designed to promote modularity, reusability, and maintainability in software development. There are four core principles of OOP, often referred to as the “four pillars” of OOP. These principles are:
-
Encapsulation:
Encapsulation refers to the bundling of data (attributes) and methods (functions) that operate on that data into a single unit called a class. It restricts direct access to the internal state of an object, providing controlled access through well-defined interfaces (public methods). Encapsulation helps in hiding the internal complexity of an object and allows for better control over data integrity and validation.
-
Abstraction:
Abstraction involves simplifying complex reality by modeling classes based on the essential properties and behaviors that an object should have. It hides the unnecessary implementation details and only exposes what is relevant to the user. Abstraction helps in managing the complexity of a system by providing a high-level view, which makes it easier to understand and work with the system’s components.
-
Inheritance:
Inheritance allows one class (subclass or derived class) to inherit the properties and behaviors (attributes and methods) of another class (superclass or base class). This promotes code reuse and the creation of a hierarchy of classes. The subclass can extend or specialize the behavior of the superclass while inheriting its common traits. Inheritance helps in maintaining a clear and organized class structure.
-
Polymorphism:
Polymorphism means the ability of different classes to be treated as instances of the same class through a common interface. It allows objects of different classes to be used interchangeably based on their shared methods or behaviors. Polymorphism is achieved through method overriding and method overloading. This principle enables more flexible and extensible code by allowing the same method name to behave differently in different contexts.
These principles collectively provide a foundation for designing modular, flexible, and maintainable software systems. By adhering to these principles, developers can create code that is easier to understand, modify, and extend over time. OOP languages like Java, C++, Python, and others are built around these principles, making it easier to implement and practice OOP concepts in real-world projects.
9. What is Boxing and Unboxing?
Boxing and unboxing represent programming concepts frequently linked with languages supporting fundamental data types (such as int, float, char) alongside object-oriented functionalities. These concepts are particularly prevalent in languages like Java and C#.
Boxing: Boxing converting a value type into an object type . This process enables seamless storage and manipulation within programming languages. This is necessary when you want to use value types in scenarios that require reference types, such as using collections (like lists or arrays) that store objects.
For example, let’s say you have an int
variable in C#:
int myNumber = 42;
If you need to store this int
in a collection that only accepts objects (reference types), you would need to box it:
object boxedNumber = myNumber; // Boxing
Here, boxedNumber
is an instance of the object
class that holds the value of myNumber
. This allows you to store the integer in collections that expect reference types.
Unboxing: Unboxing is the reverse process of boxing. It involves extracting the value from an object type and converting it back into a value type. This is necessary when you retrieve a value from a collection (stored as an object) and need to work with it as a value type again.
Continuing from the previous example:
int unboxedNumber = (int)boxedNumber; // Unboxing
In this case, (int)boxedNumber
is casting the boxed object back into an int
value, allowing you to use it as a regular integer.
Both boxing and unboxing involve a performance overhead because they require memory allocations and conversions. Furthermore, errors may arise when attempting unboxing on an object that has not been boxed with the appropriate value type. It’s important to be mindful of these concepts, especially in performance-critical code. In some cases, languages like C# provide alternatives like using generic collections (List<int>
instead of List<object>
) to avoid the need for boxing and unboxing.
10. What is Coupling and Cohesion?
Coupling and cohesion are two fundamental concepts in software engineering that describe the relationships between modules or components within a software system.
-
Coupling:
Coupling refers to the degree of interdependence between different modules or components in a software system. It measures how closely two or more modules are connected or reliant on each other. There are different levels of coupling, ranging from loose (low) to tight (high)
-
Low Coupling:
In a system with low coupling, modules are relatively independent and have minimal interaction with each other. Changes in one module are unlikely to have a significant impact on other modules. This promotes modularization, reusability, and easier maintenance.
-
High Coupling:
In a system with high coupling, modules are closely interconnected, and changes in one module can have ripple effects on others. This can lead to a lack of flexibility, increased complexity, and difficulties in maintaining and modifying the system.
Reducing coupling is generally desirable in software design, as it helps create more flexible and maintainable systems. Design patterns, such as the Dependency Injection pattern, are often used to achieve low coupling between components.
- Cohesion: Cohesion refers to the degree to which the elements within a module or component are related to each other. It measures how well the responsibilities and functionality within a module are focused and unified. Like coupling, cohesion can also be categorized into different levels:
- High Cohesion: In a module with high cohesion, the elements (functions, classes, or methods) within that module are closely related and work together to achieve a single, well-defined purpose or functionality. This promotes clarity, ease of understanding, and maintainability.
- Low Cohesion: In a module with low cohesion, the elements within that module might have a variety of unrelated functions or responsibilities. This can lead to confusion, difficulty in understanding the module’s purpose, and challenges in maintenance.
Designing modules with high cohesion is generally considered better, as it helps create more focused, understandable, and easily maintainable code.
In summary, while coupling and cohesion are somewhat opposing concepts, they both play crucial roles in software design. A well-designed software system aims for low coupling between modules and high cohesion within modules to achieve maintainability, flexibility, and comprehensibility.