Java + OOP

What is OOP?

Object-oriented programming (OOP) is a programming paradigm that is based on the concept of objects.

Objects are instances of classes. A class is like a blueprint for creating objects which define the structure and behavior of the objects. It contains properties (data) and methods (functions) that define what the objects can do and how they interact with other objects.

  1. Methods: Methods are the actions that objects can perform

  2. Attributes: Attributes are the details about an object.

OOP emphasizes concepts such as inheritance, encapsulation and polymorphism, which enable code to be more modular, flexible and reusable. It’s widely used in software development for creating complex applications and systems.

For example, an online shopping application might be designed using OOP principles, with classes such as Product.

The Product class is defined with fields name, price, rating, and description.

Object of Product class can be laptop which has a name, price, rating and description

Why Do We Need OOP?

OOP helps to organize complex software systems by breaking them into manageable pieces. It promotes:

1. Modularity

Explanation:

  • OOP allows developers to break down complex problems into smaller, more manageable pieces (classes and objects). Each class can be developed, tested, and debugged independently.

Example: Consider an online shopping system where different parts such as Product, Customer, and Order are developed as separate classes. This modularity makes it easier to manage and maintain the system.

2. Reusability

Explanation:

  • OOP promotes code reusability through inheritance and polymorphism.

  • Developers can create new classes by extending existing ones, reducing redundancy.

Example: A Vehicle class can be reused to create more specific classes like Car and Bike.

3. Scalability and Maintainability

Explanation:

  • OOP systems are easier to scale as new functionality can be added with minimal changes to existing code.

  • Encapsulation ensures that internal details of objects are hidden, leading to less interdependency and easier maintenance.

Example: Adding a new type of payment method in an online shopping system only requires creating a new class without affecting existing classes.

4. Abstraction

Explanation:

  • Abstraction simplifies complex systems by hiding implementation details and exposing only essential features.

  • This makes it easier for developers to work with large systems without needing to understand every detail.

Example: An abstract class Shape can define the concept of a shape without specifying the details of any particular shape.

Class vs Object including real life examples.

  • Class:

    1. A class is a template/blueprints for building objects (CAR)

    2. They define what objects look likes and what it can do.

    3. Example: Class Carif you were building a car, the class might specify that cars have wheels, doors, and engines, and can move forward, backward, or turn.

  • Object:

    1. An object is an instance of a class.

    2. When the individual objects are created, they inherit all the variables and methods from the class.

    3. Example: Object of Class Car is Volvo, Audi and Toyota. Each has its own characteristic.

    Difference between Class vs Objects
    Class as Blueprint
    Objects

What are the main principles of OOP?

  1. Encapsulation

  2. Inheritance

  3. Polymorphism

  4. Abstraction

What is Encapsulation? Explain with a code. Why it is important or needed and how?

Encapsulation

Encapsulation means binding our data with methods in a single unit /class only ways to access to those data is methods and nobody can outside directly access this variable

Benefits:

  1. Setter methods can include validation logic to ensure that any data being set meets certain criteria

    1. Example: check the amount > 500 in Bank Class deposit()

    2. Hides the implementation logics of validation

  2. Can set read-only or write-only access only to that variable

    1. Example: read-only access to accounNumber in Bank Class

  3. Hides implementation logics and rest of the code depends on the method only. you can change implementation logics any time any outside can't don't know about it.

    1. Example : withdraw() and deposit() function in Bank Classs

Abstraction vs Encapsulation

Abstraction is a design-level process but encapsulation is an implementation process. Encapsulation tells us how exactly you can implement abstraction in the program. Abstraction pertains to only displaying the essential details to the user whereas encapsulation pertains to typing up all the data members and associated member functions into a single abstracted unit.

Access modifiers āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻ•āĻŋ āϜāĻžāύ? āĻ•āύāϟāĻžāϰ āĻ•āĻžāϜ āĻ•āĻŋ ?

There are 4 keywords for this simple but important action: Public, Private, Default, Protected. We call them “Access Modifiers” and any data structure declaration starts with them.

In Java, access modifiers are used to set the accessibility (visibility) of classes, interfaces, variables, methods, constructors, data members, and the setter methods.

  1. Public: When a class, method, or variable is declared as public, it means it can be accessed from any other class in the Java program, whether they’re in the same package or in a different package.

  2. Private: When a class, method, or variable is declared as private, it can only be accessed within the same class. It’s not visible to other classes, including subclasses and classes from the same package.

  3. Protected: When a class, method, or variable is declared as protected, it can be accessed within the same package and also from subclasses in any package. However, it can’t be accessed from non-subclass classes in different packages.

  4. Default(Package-Private): When no access modifier is specified, it’s known as default or package-private. This means the class, method, or variable can be accessed from any class within the same package, but not from outside the package.

What is Interface and Why do we use it in Software Development?

Notes on Interfaces: An interface in Java is a mechanism used to achieve abstraction. Interfaces allow you to define a contract for classes, specifying what methods a class must implement.

  • Like abstract classes, interfaces cannot be used to create objects

  • Interface methods do not have a body - the body is provided by the "implement" class

  • On implementation of an interface, you must override all of its methods

  • Interface methods are by default abstract and public

  • Interface attributes are by default public, static and final

  • An interface cannot contain a constructor (as it cannot be used to create objects)

Why And When to Use Interfaces?

1) To achieve security - hide certain details and only show the important details of an object (interface).

2) Java does not support "multiple inheritance" (a class can only inherit from one superclass). However, it can be achieved with interfaces, because the class can implement multiple interfaces. Note: To implement multiple interfaces, separate them with a comma.

interface FirstInterface {
  public void myMethod(); // interface method
}

interface SecondInterface {
  public void myOtherMethod(); // interface method
}

class DemoClass implements FirstInterface, SecondInterface {
  public void myMethod() {
    System.out.println("Some text..");
  }
  public void myOtherMethod() {
    System.out.println("Some other text...");
  }
}

What is Abstraction in Java? Why and How Abstract vs Interface?

It is the process of hiding the implementation details and only showing the functionality to the users

Example: ATM Machine cash out process we just see the interface don't know the implementation behind it.

Benefits of Abstraction:

  1. Easier to extends in future cause less coupling

  2. Reuse Code and reduce duplicating

Abstract Class (0 - 100% Abstraction)

It is a special type of class that cannot be directly initiated or cannot create objects of it which mainly used to sever as a blueprint and define a contract the subclasses must adhere to do or follow it.

Create abstract classes when you want to provide a common base class with some default behavior.

It can have abstract methods (methods without implementation) (Subclasses are mandated to provide their own implementation for these methods.) and non-abstract methods (methods with implementation).

  • Subclasses of an abstract class must implement its abstract methods.

  • Use when you want to share common functionality in related classes.

  • Use when subclass must need to implement a method (abstract method) on their own.

  • If our base contract keeps on changing then interfaces can cause issues because we can’t declare additional methods to the interface without changing all the implementation classes, with the abstract class we can provide the default implementation and only change the implementation classes that are actually going to use the new methods.

Example:

Abstract class: payment (data , initatePayment(), validatePayment())

Subclass : Credicard , Bitcoin, Bkash

What is interface?

An interface is a collection of abstract methods, which means they do not have a body. You can only implement them in a class

It is a mechanism to achieve 100% abstraction which only contains abstract methods only (only method name and no body no implementation) and can only have static-final variables only we use it normally when some unrelated class have common functionality method but own implementation logic..we can also implements multiple interfaces under a class which indirectly mean multiple inheritance. Suppose we have two unrelated class : dog - cat which have two function eat() - bark()..each of the class have their own implementation but here we can use a interface name animal and it will two abstract methods eat() - bark()..who ever implements will need add their own implementation.. now can access the interface do not need to what behind the function.

then when to use abstract?

we will abstract class when our related subclass has something common (same implementation) but they can have something which has different implementation for each class Shape

  • Concrete : data, showShape()

  • Abstract : calculateShape() Subclass : rectange, circle, triangle

Interface (100% Abstraction)

An interface is a contract that specifies a set of methods without providing their implementations. It acts as a blueprint for classes that must implement these methods.

Interfaces enable multiple classes to share a common set of methods.

It can have only abstract methods (methods without implementation)

  • Use when you have many unrelated classes then need to perform a certain common action

  • Use when you want to apply multiple interfaces to a class (Multiple Inheritance)

  • Cannot have constructor

  • Only static - final variable: they also must be initialized

What is the difference between Abstract class and Interface?

Abstract Class
Interface

An abstract class can contain both abstract and non-abstract methods: (methods with or without implementation)

Interface contains only abstract methods. (only methods without implementation)

An abstract class can have all four; static, non-static and final, non-final variables.

Only final and static variables are used.

Abstract classes methods can have access modifiers as public, private, protected, static

Interface methods are implicitly public and abstract

To declare abstract class abstract keywords are used.

The interface can be declared with the interface keyword.

The keyword extend is used to extend an abstract class

The keyword implement is used to implement the interface.

It does not support multiple inheritance

It supports multiple inheritance.

Abstract classes can have constructors

Interfaces can’t have constructors.

Use an abstract class when you have multiple related classes that share common behavior and fields.

Use an interface when you have multiple unrelated classes that need to implement a common behavior.

we'll look at a payment processing system for an e-commerce platform. The system needs to support multiple payment methods such as Credit Card, PayPal, and Bitcoin. We'll use abstraction to define a general payment process and then implement specific payment methods.

we'll create a notification system for an application that can send notifications via different channels such as Email, SMS, and Push notifications. We'll use Java interfaces to define the contract for notification services and implement different notification methods.

Why is the interface needed? āφāĻŽāĻŋ āϤ āϚāĻžāχāϞ⧇ class use āĻ•āϰāϤ⧇ āĻĒāĻžāϰāϤāĻžāĻŽ, āφāϞāĻžāĻĻāĻž āĻ•āϰ⧇ interface āϕ⧇āύ āĻĻāϰāĻ•āĻžāϰ? Abstract class and interface āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ āϕ⧀? āϕ⧋āύāϟāĻž āϕ⧇āύ āχāωāϜ āĻ•āϰ⧇?

When to use abstract classes and when to use interfaces?

Ans: Abstract vs Interface

Use the knowledge of previous question

What is polymorphism? Polymorphism āĻāϰ āĻĒā§āϰāĻ•āĻžāϰāϭ⧇āĻĻāĨ¤ āĻ•āύāϟāĻž āĻ•āĻ–āύ use āĻšā§Ÿ?

Ans: What is Polymorphism?

Same thing behaves differently on different occasion

  • The behavior of a method depends on the data provided.

  • The functionality of a method changes according to different scenarios.

  1. Compile time -Method overloading

int calculateSalary(int hours, int payFee)

int calculateSalary(int hours, int payFee, int bonus)

  1. Runtime time - Method overriding

Parent Class : Employee

int calculateSalary(int salary) { return salary; }

Child Class: SeniorEmployee

int calculateSalary(int salary) { return salary + salary*10%; }

Advantages :

  • Simplifies coding by reducing the number of method

  • Polymorphism allows for more flexible and dynamic code, where the behavior of an object can change at runtime depending on the context in which it is being used

  • Polymorphism enables code extensibility, as new subclasses can be created to extend the functionality of the superclass without modifying the existing code.

  • It can reduce the complexity of code by allowing the use of the same method name for related functionality,

Two Types of Polymorphism 👍

  1. Method Overloading / Compile Polymorphism

  2. Method Overriding / Run-Time Polymorphism

Why use Polymorphism?

  1. Better Organization: Polymorphism allows for better organization of code by grouping related functionality in one class.

  2. Code Extensibility: Polymorphism enables code extensibility, as new subclasses can be created to extend the functionality of the superclass without modifying the existing code.

  3. Increased Efficiency: Compile-time polymorphism can lead to more efficient coding. The compiler can choose the appropriate method to call at compile time, based on the number, types, and order of arguments passed to it

  4. Code Reusability: Polymorphism provides the reuse of code, as methods with the same name can be used in different classes.

What is the difference between polymorphism and inheritance in Java?

Polymorphism is a concept where a function is defined in more than one form whereas in inheritance, a new class inherits the features from an already existing class. The concept of polymorphism applies to functions or methods whereas inheritance applies to classes.

Method overloading vs Method overriding āĻ•āĻŋ ? āĻāĻ•āϟāĻž example āĻĻāĻžāĻ“āĨ¤

  1. Method Ridding 👍 : During inheritance in Java, if the same method is present in both the superclass and the subclass. Then, the method in the subclass overrides the same method in the superclass. This is called method overriding.

    The method that is called is determined during the execution of the program. Hence, method overriding is a run-time polymorphism.

  2. Method Overloading: In a Java class, we can create methods with the same name if they differ in parameters. This is known as method overloading in Java.

    The method that is called is determined by the compiler. Hence, it is also known as compile-time polymorphism.

Can the return type of method be different in method overloading? If yes why, and if not why?

Describe about inheritance in OOP?

Inheritance in Java is a fundamental concept in object-oriented programming (OOP) that allows one class to acquire the properties and behaviors of another class.

Base Class: Customer

Subclass: regularCustomer,vipCustomer,PremimumCustomer

Benefits:

  • Reuse code and avoid duplication

  • Create a hierarchy of classes

  • To create subclass type and a common base class

  • New classes can be created with minimal changes to existing code

  • Inheritance in Java is a fundamental concept in object-oriented programming (OOP) that allows one class to acquire the properties and behaviors of another class.

  • This mechanism enables the creation of new classes based on existing ones, promoting code reusability and method overriding for achieving runtime polymorphism.

  • Key Concepts of Inheritance:

    • Superclass (Parent Class): The class whose properties and behaviors are inherited.

    • Subclass (Child Class): The class that inherits from the superclass.

    • Extends Keyword: Used to indicate inheritance, signifying that a subclass is derived from a superclass.

    • IS-A Relationship: Describes the inheritance relationship, indicating that a subclass is a type of its superclass.

    • Example: Vehicle is Superclass and Car, Truck in Subclass.. Here Subclass will acquire the behavior and properties of superclass and implement in their own style.

  • Multilevel Inheritance: Exists when a class extends a class that extends another class, forming a chain of inheritance

  • In this example, Car is a subclass of Vehicle, inheriting the start() and stop() methods from Vehicle. Additionally, Car introduces a new property numberOfSeats.

public class Vehicle {
    public void start() {
        // starting the engine
    }
    public void stop() {
        // stopping the engine
    }
}

public class Car extends Vehicle {
    int numberOfSeats = 4;

    public int getNumberOfSeats() {
        return numberOfSeats;
    }
}
public class Truck extends Vehicle {
    int numberOfSeats = 2;

    public int getNumberOfSeats() {
        return numberOfSeats;
    }
}

Inheritance: Customer Management System

In an e-commerce platform, you often have different types of customers, such as regular customers and premium customers. Each customer type has some common attributes but also some specific features. By using inheritance, we can streamline the design of the system.

Base Class: Customer

public class Customer {
    private String customerId;
    private String name;
    private String email;
    private String phoneNumber;
    
    public Customer(String customerId, String name, String email, String phoneNumber) {
        this.customerId = customerId;
        this.name = name;
        this.email = email;
        this.phoneNumber = phoneNumber;
    }
    
    public void displayCustomerInfo() {
        System.out.println("Customer ID: " + customerId);
        System.out.println("Name: " + name);
        System.out.println("Email: " + email);
        System.out.println("Phone Number: " + phoneNumber);
    }
    
    // Getters and setters
}

Derived Class: RegularCustomer

public class RegularCustomer extends Customer {
    private double discountRate;
    
    public RegularCustomer(String customerId, String name, String email, String phoneNumber, double discountRate) {
        super(customerId, name, email, phoneNumber);
        this.discountRate = discountRate;
    }
    
    public double getDiscountRate() {
        return discountRate;
    }
    
    public void setDiscountRate(double discountRate) {
        this.discountRate = discountRate;
    }
    
    @Override
    public void displayCustomerInfo() {
        super.displayCustomerInfo();
        System.out.println("Discount Rate: " + discountRate + "%");
    }
}

Derived Class: PremiumCustomer

public class PremiumCustomer extends Customer {
    private String membershipLevel;
    
    public PremiumCustomer(String customerId, String name, String email, String phoneNumber, String membershipLevel) {
        super(customerId, name, email, phoneNumber);
        this.membershipLevel = membershipLevel;
    }
    
    public String getMembershipLevel() {
        return membershipLevel;
    }
    
    public void setMembershipLevel(String membershipLevel) {
        this.membershipLevel = membershipLevel;
    }
    
    @Override
    public void displayCustomerInfo() {
        super.displayCustomerInfo();
        System.out.println("Membership Level: " + membershipLevel);
    }
}

Explanation to the Interviewer

"In a recent project, I worked on an e-commerce platform where we needed to manage different types of customers. We used inheritance to streamline our Customer Management System.

We had a base class Customer that encapsulated common attributes like customerId, name, email, and phoneNumber. This class also included a method to display customer information.

From this base class, we derived two specific classes: RegularCustomer and PremiumCustomer. Each of these classes had additional attributes and behaviors. For example, RegularCustomer had a discountRate, while PremiumCustomer had a membershipLevel. Both classes inherited the common attributes and methods from the Customer class, but they also had their own specific methods and overrides.

This use of inheritance allowed us to reuse code efficiently and made our system more maintainable. Whenever we needed to make changes to common customer attributes or methods, we only had to do it in one place, the Customer class, and all derived classes automatically inherited these changes. This design also made it easy to extend the system with new customer types in the future."

This example demonstrates a practical and real-life application of inheritance in a Customer Management System, which should be a compelling use case for your interview.

If there were no inheritance concept, then which problems could occur?

  1. Code Duplication: Without inheritance, developers would need to rewrite similar code across different classes. This not only increases the size of the codebase but also makes it harder to maintain and update. For instance, if you had classes representing different types of vehicles (cars, trucks, bikes), without inheritance, you'd have to manually copy the common methods (like startEngine(), stopEngine()) into each class, leading to redundant code.

  2. Limited Code Reusability: Inheritance allows for the reuse of code through the creation of subclasses. Without it, achieving code reusability becomes much more challenging.

  3. Difficulty in Extending Functionality: Inheritance provides a straightforward way to add new features to existing classes. Without it, extending the functionality of a class requires more complex solutions, such as modifying the original class or creating entirely new classes that mimic the desired behavior. This can complicate the process of adding new features and maintaining the overall structure of the application.

  4. Lack of Polymorphism: Polymorphism, which allows objects of different classes to be treated as objects of a common superclass, relies heavily on inheritance. Without inheritance, achieving polymorphism becomes difficult, limiting the flexibility and adaptability of the code.

  5. Impact on Design Patterns: Many design patterns in object-oriented programming rely on inheritance to simplify their implementation. Without inheritance, applying these patterns becomes more complicated, potentially leading to less elegant and less effective solutions.

    1. Factory Method Pattern

    2. Adapter Pattern

    3. Liskov Substitute Principle

What should I do to restrict a class to be inherited by other classes?

Ans: If you don't want other classes to inherit from a class, use the final keyword:

final class Vehicle {
  ...
}
// If you try to access a final class, Java will generate an error:
class Car extends Vehicle {
  ...
}

Which language supports multiple inheritance?

Ans: Java doesn’t support multiple extends, but we can use multiple implements in java. In python we can do multiple implements and extends.

OOP āĻāϰ āĻāĻ•āϟāĻž multilevel inheritance āĻĻ⧇ āĻ–āĻŋ ā§Ÿā§‡ āĻāϰ code āĻĻ⧇ āĻ–āĻŋ ā§Ÿā§‡ ask āĻ•āϰāϏ⧇ āĻāϟāĻžāϰ output āĻ•āĻŋ ? output āĻāϰāĻ•āĻŽ āφāϏāĻžāϰ āϜāĻ¨ā§āϝ āĻāχ code āĻ āĻ•āĻŋ āĻ•āĻŋ āĻ•āϰāĻž āϞāĻžāĻ—āϤ |

What is the output of this code? https://gist.github.com/Mahdi-Hasan/0374280653144e87422b25f1aa7a6834

The Diamond Problem

The "diamond problem" (sometimes referred to as the "Deadly Diamond of Death"[6]) is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If there is a method in A that B and C have overridden, and D does not override it, then which version of the method does D inherit: that of B, or that of C?

Ans : In Java, the "diamond problem" is avoided through its inheritance mechanism. Java does not support multiple inheritance of classes. Java classes can only inherit from one class. Thus, the diamond problem does not occur with classes. When a class inherits another class, it cannot inherit from more than one class, so there is no ambiguity.

Interfaces: Java allows a class to implement multiple interfaces.

In java how to call a method without creating an object?

Ans: In Java, you can call a method without creating an object if the method is defined as a static method. A static method belongs to the class itself rather than an instance of the class. Here’s how you can define and call a static method:

public class Utility {
    // Static method definition
    public static int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        // Call static method without creating an object
        int sum = Utility.add(5, 3);
        System.out.println("The sum is: " + sum);
    }
}

In this example, add is a static method in the Utility class. The main method calls add directly using the class name Utility.

By using static methods, you can avoid the need to instantiate a class to use certain methods that logically belong to the class itself rather than any particular object.

I want if a class one to extend another class , it must have to override one method. How to do it?

In Java, if you want to enforce that any subclass of a given class must override a particular method, you can achieve this by defining an abstract method in the base class. Here’s how you can do it:

  1. Define an Abstract Base Class:

    • Mark the class as abstract.

    • Declare the method you want to enforce as abstract.

  2. Extend the Abstract Base Class:

    • Any subclass of the abstract class must provide an implementation for the abstract method.

Here is an example demonstrating this:

Step 1: Define an Abstract Base Class

public abstract class BaseClass {
    // Abstract method that must be overridden by subclasses
    public abstract void myMethod();
    
    // You can also have concrete methods in an abstract class
    public void concreteMethod() {
        System.out.println("This is a concrete method in the base class.");
    }
}

Step 2: Extend the Abstract Base Class

public class SubClass extends BaseClass {
    // Override the abstract method
    @Override
    public void myMethod() {
        System.out.println("myMethod is overridden in SubClass.");
    }
}

public class Main {
    public static void main(String[] args) {
        SubClass obj = new SubClass();
        obj.myMethod();  // Calls the overridden method in SubClass
        obj.concreteMethod();  // Calls the concrete method in BaseClass
    }
}

Explanation

  • Abstract Class: BaseClass is marked as abstract, and it contains an abstract method myMethod(). This method does not have a body and must be implemented by any subclass.

  • Subclass: SubClass extends BaseClass and provides an implementation for the abstract method myMethod().

  • Concrete Methods: BaseClass can also have concrete methods like concreteMethod(), which subclasses can use without needing to override.

By declaring myMethod as abstract in the base class, Java enforces that any non-abstract subclass of BaseClass must provide an implementation for myMethod.

What is Constructor and its type?

In Java, a constructor is a special method that is called when an object is instantiated. Its primary purpose is to initialize the newly created object. A constructor has the same name as the class and does not have a return type.

Types of Constructors

  1. Default Constructor: This is a constructor provided by Java if no constructors are defined in a class. It initializes the object with default values.

  2. Parameterized Constructor: This constructor allows you to provide initial values for the object at the time of creation. It takes arguments to initialize object properties.

Example of Constructors

// Default Constructor
class Car {
    String color;
    int year;

    // Default constructor
    Car() {
        color = "White";
        year = 2020;
    }
}

// Parameterized Constructor
class Bike {
    String brand;
    int speed;

    // Parameterized constructor
    Bike(String b, int s) {
        brand = b;
        speed = s;
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating an object using default constructor
        Car car1 = new Car();
        System.out.println("Car color: " + car1.color + ", Year: " + car1.year);

        // Creating an object using parameterized constructor
        Bike bike1 = new Bike("Yamaha", 120);
        System.out.println("Bike brand: " + bike1.brand + ", Speed: " + bike1.speed);
    }
}

If parent class has constructor and child class has also its constructor which will be called first in while accessing child object?

Constructor Invocation in Inheritance

When a child class inherits from a parent class, the constructor of the parent class is called first before the constructor of the child class. This is because the child class constructor implicitly calls the parent class constructor using super(). If no explicit call to super() is made, the default no-argument constructor of the parent class is called.

Example of Constructor Invocation in Inheritance

class Parent {
    // Parent class constructor
    Parent() {
        System.out.println("Parent class constructor called");
    }
}

class Child extends Parent {
    // Child class constructor
    Child() {
        // Implicit call to super() happens here
        System.out.println("Child class constructor called");
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating an instance of Child class
        Child child = new Child();
    }
}

Output:

Parent class constructor called
Child class constructor called

Explanation:

  • When the Child object is created, the Child class constructor is invoked.

  • Before the Child class constructor executes, the Parent class constructor is called implicitly using super().

  • Thus, the output shows that the parent class constructor is executed first, followed by the child class constructor.

If the parent class constructor requires parameters, the child class must explicitly call it using super(parameters).

Example with Parameterized Constructor in Parent Class

class Parent {
    // Parent class constructor with parameter
    Parent(String message) {
        System.out.println("Parent class constructor called: " + message);
    }
}

class Child extends Parent {
    // Child class constructor
    Child() {
        // Explicit call to parent class constructor
        super("Hello from Parent");
        System.out.println("Child class constructor called");
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating an instance of Child class
        Child child = new Child();
    }
}

Output:

Parent class constructor called: Hello from Parent
Child class constructor called

In this example, the Child class constructor explicitly calls the Parent class constructor with a parameter using super("Hello from Parent").

What is Super? Write the use cases of Super?

In Java, super is a keyword used to refer to the immediate parent class object. It is primarily used to access methods and constructors of the parent class. There are three main uses of super in Java:

  1. Calling the Parent Class Constructor:

    • super() is used to call the parent class constructor. If the parent class constructor requires parameters, you can pass them as arguments to super().

  2. Accessing Parent Class Methods:

    • super can be used to call a method in the parent class that has been overridden in the child class.

  3. Accessing Parent Class Variables:

    • super can be used to access a variable in the parent class if there is a variable with the same name in the child class.

Example: Using super to Call Parent Class Constructor

class Parent {
    Parent(String message) {
        System.out.println("Parent constructor called: " + message);
    }
}

class Child extends Parent {
    Child() {
        // Explicit call to parent class constructor
        super("Hello from Parent");
        System.out.println("Child constructor called");
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
    }
}

Output:

Parent constructor called: Hello from Parent
Child constructor called

Example: Using super to Call Parent Class Method

class Parent {
    void display() {
        System.out.println("Display method in Parent");
    }
}

class Child extends Parent {
    void display() {
        System.out.println("Display method in Child");
    }

    void show() {
        // Call the display method of Parent class
        super.display();
        // Call the display method of Child class
        display();
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.show();
    }
}

Output:

Display method in Parent
Display method in Child

Example: Using super to Access Parent Class Variable

class Parent {
    int num = 100;
}

class Child extends Parent {
    int num = 200;

    void display() {
        // Accessing parent class variable
        System.out.println("Parent num: " + super.num);
        // Accessing child class variable
        System.out.println("Child num: " + num);
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.display();
    }
}

Output:

Parent num: 100
Child num: 200

Summary

  • super is used to refer to the immediate parent class object.

  • super() calls the parent class constructor.

  • super.methodName() calls a method in the parent class.

  • super.variableName accesses a variable in the parent class.

What is this in Java? Write the use cases of it?

In Java, this is a keyword that refers to the current instance of the class. It is used to differentiate between instance variables and parameters, invoke constructors, and pass the current object as an argument to a method.

Uses of this in Java

  1. Distinguishing Instance Variables from Parameters:

    • this is used to refer to instance variables when their names are shadowed by method or constructor parameters.

  2. Calling a Constructor from Another Constructor:

    • this() is used to call another constructor from within the same class.

  3. Passing the Current Object as a Parameter to Another Method:

    • this can be used to pass the current object as an argument to another method.

  4. Returning the Current Object:

    • this can be used to return the current object from a method.

Example 1: Distinguishing Instance Variables from Parameters

class Example {
    int num;

    // Constructor with a parameter
    Example(int num) {
        this.num = num; // 'this.num' refers to the instance variable
    }

    void display() {
        System.out.println("Number: " + this.num);
    }

    public static void main(String[] args) {
        Example obj = new Example(10);
        obj.display();
    }
}

Output:

Number: 10

Example 2: Calling a Constructor from Another Constructor

class Example {
    int num;
    String message;

    // Default constructor
    Example() {
        this(10, "Hello"); // Calls the parameterized constructor
    }

    // Parameterized constructor
    Example(int num, String message) {
        this.num = num;
        this.message = message;
    }

    void display() {
        System.out.println("Number: " + this.num + ", Message: " + this.message);
    }

    public static void main(String[] args) {
        Example obj = new Example();
        obj.display();
    }
}

Output:

Number: 10, Message: Hello

Example 3: Passing the Current Object as a Parameter to Another Method

class Example {
    int num;

    Example(int num) {
        this.num = num;
    }

    void display() {
        System.out.println("Number: " + this.num);
    }

    void show(Example obj) {
        obj.display();
    }

    void callShow() {
        this.show(this); // Passes the current object to the show method
    }

    public static void main(String[] args) {
        Example obj = new Example(20);
        obj.callShow();
    }
}

Output:

Number: 20

Example 4: Returning the Current Object

class Example {
    int num;

    Example(int num) {
        this.num = num;
    }

    Example getObject() {
        return this; // Returns the current object
    }

    void display() {
        System.out.println("Number: " + this.num);
    }

    public static void main(String[] args) {
        Example obj1 = new Example(30);
        Example obj2 = obj1.getObject();
        obj2.display();
    }
}

Output:

Number: 30

Summary

  • this keyword refers to the current instance of the class.

  • Used to differentiate between instance variables and method/constructor parameters.

  • this() calls another constructor within the same class.

  • this can pass the current object to methods or return it from methods.

  • Essential for clear and precise object-oriented programming in Java.

What is Final in Java?

In Java, the final keyword is used to restrict the usage of variables, methods, and classes. It has different implications depending on where it is applied:

  1. Final Variables:

    • When a variable is declared as final, it means that its value cannot be changed once it is initialized. This makes the variable a constant.

    final int MAX_VALUE = 100;
    • For instance variables, final ensures that the variable is assigned only once. It must be initialized either at the time of declaration or within the constructor.

  2. Final Methods:

    • When a method is declared as final, it cannot be overridden by subclasses. This is useful to prevent altering the intended behavior of a method.

    public final void display() {
        System.out.println("This method cannot be overridden");
    }
  3. Final Classes:

    • When a class is declared as final, it cannot be subclassed. This is used to prevent inheritance.

    public final class Constants {
        // class body
    }
  4. Final Parameters:

    • Method parameters can also be declared as final, which means they cannot be reassigned within the method.

    public void print(final int number) {
        // number = 5; // This will cause a compilation error
        System.out.println(number);
    }
  5. Final with Local Variables:

    • Local variables in methods or blocks can be declared as final. This means that once they are assigned a value, it cannot be changed.

    public void method() {
        final int localVar = 10;
        // localVar = 20; // This will cause a compilation error
    }

Use Cases of final:

  • Immutability: When you want to ensure that a variable's value remains constant throughout the execution of the program.

  • Security: Preventing modification of methods and classes can enhance security and integrity, especially in sensitive applications.

  • Optimization: The Java compiler can optimize the code better when it knows that certain values will not change.

Example:

public final class MyFinalClass {
    private final int value;

    public MyFinalClass(int value) {
        this.value = value;
    }

    public final void display() {
        System.out.println("Value: " + value);
    }
}

class Test {
    public static void main(String[] args) {
        final MyFinalClass obj = new MyFinalClass(10);
        obj.display();
        
        // obj = new MyFinalClass(20); // This will cause a compilation error
    }
}

In this example:

  • MyFinalClass is a final class, so it cannot be subclassed.

  • value is a final instance variable, so it can only be assigned once.

  • display is a final method, so it cannot be overridden.

  • obj is a final reference, so it cannot be reassigned to another object.

What are the ways to prevent a class from being instantiated?

In Java, there are several ways to prevent a class from being instantiated. These methods are typically used to ensure that a class cannot be instantiated directly, often because it is intended to serve as a utility class or to enforce the use of certain design patterns. Here are some common techniques:

  1. Make the Class Abstract:

    • Declaring a class as abstract prevents it from being instantiated directly. Abstract classes can still have constructors, fields, and methods, and they can be subclassed.

    public abstract class UtilityClass {
        // Constructor
        public UtilityClass() {
            // Initialization code
        }
    
        // Methods
        public static void utilityMethod() {
            // Method code
        }
    }
  2. Private Constructor:

    • Declaring the constructor as private prevents any external classes from creating an instance of the class. This is commonly used in singleton patterns or utility classes.

    public final class MathUtils {
        // Private constructor to prevent instantiation
        private MathUtils() {
            throw new UnsupportedOperationException("Cannot instantiate MathUtils");
        }
    
        // Static method for addition
        public static int add(int a, int b) {
            return a + b;
        }
    
        // Static method for subtraction
        public static int subtract(int a, int b) {
            return a - b;
        }
    }
    public class TestMathUtils {
        public static void main(String[] args) {
            // Using the static methods of MathUtils
            int sum = MathUtils.add(5, 3);
            int difference = MathUtils.subtract(5, 3);
    
            // Print the results
            System.out.println("Sum: " + sum);
            System.out.println("Difference: " + difference);
    
            // Attempting to instantiate MathUtils will cause an error
            // MathUtils utils = new MathUtils(); // This will cause a compilation error
        }
    }

What is static variable and methods in Java?

In Java, the static keyword is used to indicate that a particular member (variable, method, or nested class) belongs to the class itself rather than to instances of the class.

Static Variables

Explanation:

  • A static variable is shared among all instances of the class.

  • It is initialized only once, at the start of the execution.

Example:

public class Counter {
    public static int count = 0;

    public Counter() {
        count++;
    }
}

public class TestCounter {
    public static void main(String[] args) {
        Counter c1 = new Counter();
        Counter c2 = new Counter();
        Counter c3 = new Counter();

        System.out.println(Counter.count); // Outputs: 3
    }
}

In this example, the count variable is static, meaning it is shared among all instances of the Counter class. Every time a new Counter object is created, count is incremented.

Static Methods

Explanation:

  • Static methods belong to the class rather than any particular object instance.

  • They can be called without creating an instance of the class.

  • Static methods can only access static variables and other static methods directly.

Example:

public class MathUtil {
    public static int add(int a, int b) {
        return a + b;
    }
}

public class TestMathUtil {
    public static void main(String[] args) {
        int result = MathUtil.add(5, 10);
        System.out.println(result); // Outputs: 15
    }
}

In this example, the add method is static, so it can be called directly using the class name MathUtil, without needing to create an instance.

Last updated