1. Can you explain the difference between abstract class and interface in Java?

Basic

1. Can you explain the difference between abstract class and interface in Java?

Overview

In Java, both abstract classes and interfaces are used to achieve abstraction, which is a fundamental concept in object-oriented programming. Understanding the difference between these two is crucial for designing robust and flexible Java applications. Abstract classes allow partial implementation while interfaces are contracts for what a class can do, without specifying how.

Key Concepts

  • Abstraction: Both abstract classes and interfaces are used to achieve abstraction in Java, which means hiding the implementation details from the user.
  • Implementation: Abstract classes can have both abstract methods (without a body) and concrete methods (with implementation), whereas interfaces can only have abstract methods (prior to Java 8) and default and static methods (Java 8 and onwards).
  • Inheritance and Implementation: A class can extend only one abstract class but can implement multiple interfaces, promoting multiple inheritance in Java through interfaces.

Common Interview Questions

Basic Level

  1. What is the difference between an abstract class and an interface in Java?
  2. Can you provide a simple example of an abstract class and an interface in Java?

Intermediate Level

  1. How do default methods in interfaces introduced in Java 8 affect the use of interfaces and abstract classes?

Advanced Level

  1. Discuss scenarios where you would prefer to use an interface over an abstract class and vice versa, considering design principles like SOLID.

Detailed Answers

1. What is the difference between an abstract class and an interface in Java?

Answer: Abstract classes and interfaces in Java serve similar purposes but are used in different scenarios. An abstract class is a class that cannot be instantiated and can contain both abstract and concrete methods. Interfaces, on the other hand, are contracts for classes that implement them, specifying what methods they must have. Before Java 8, interfaces could only have abstract methods, but now they can also have default and static methods. A key difference is that a class can extend only one abstract class but implement multiple interfaces.

Key Points:
- Abstract classes can have state (fields) and constructors, whereas interfaces cannot.
- Interfaces support multiple implementations, accommodating Java’s single inheritance limitation.
- Abstract classes are used when subclasses share a common structure or behavior, whereas interfaces are used to specify a common capability.

Example:

abstract class Vehicle {
    private String type;

    Vehicle(String type) {
        this.type = type;
    }

    abstract void move();

    void displayType() {
        System.out.println("Vehicle type: " + type);
    }
}

interface Flyable {
    void fly();
}

class Airplane extends Vehicle implements Flyable {
    Airplane() {
        super("Airplane");
    }

    @Override
    void move() {
        System.out.println("Airplane moves by flying.");
    }

    @Override
    public void fly() {
        System.out.println("Airplane flies.");
    }
}

2. Can you provide a simple example of an abstract class and an interface in Java?

Answer: Below is a simple example demonstrating the use of both an abstract class and an interface in Java. The abstract class Animal provides a general structure and common functionalities for all animals, such as the eat method, while the interface Pet specifies additional capabilities that not all animals may have.

Key Points:
- Abstract classes can be used to share code among closely related classes.
- Interfaces define a contract or capability that can be implemented by any class, related or not.
- A class can implement multiple interfaces but extend only one abstract class.

Example:

abstract class Animal {
    abstract void eat();
}

interface Pet {
    void play();
}

class Dog extends Animal implements Pet {
    void eat() {
        System.out.println("Dog eats.");
    }

    public void play() {
        System.out.println("Dog plays.");
    }
}

3. How do default methods in interfaces introduced in Java 8 affect the use of interfaces and abstract classes?

Answer: Default methods in interfaces introduced in Java 8 allow interfaces to have methods with a default implementation without breaking the implementing classes. This gives interfaces more flexibility and reduces the need for abstract classes in some scenarios. However, abstract classes are still useful when shared state or common functionality (requiring fields and constructors) is needed across various subclasses.

Key Points:
- Default methods help evolve interfaces without breaking existing implementations.
- Interfaces with default methods can provide a mix of fully abstract and implemented methods.
- Abstract classes are still preferred when a common base implementation is needed, including state management.

Example:

interface Movable {
    default void move() {
        System.out.println("Default movement.");
    }
}

class Human implements Movable {
    @Override
    public void move() {
        System.out.println("Human walks.");
    }
}

4. Discuss scenarios where you would prefer to use an interface over an abstract class and vice versa, considering design principles like SOLID.

Answer: Interfaces are preferred when you want to define a contract for what a class can do, without dictating how to do it. This is in line with the Dependency Inversion Principle of SOLID, which suggests depending on abstractions rather than concrete implementations. Interfaces are ideal for defining capabilities that can be shared across unrelated classes.

Abstract classes are preferred when a group of related classes share a common set of behaviors and states. They can be used to provide a skeleton implementation while still allowing subclasses to override methods as needed, adhering to the Open/Closed Principle.

Key Points:
- Use interfaces for capabilities that can be added to a wide range of unrelated classes.
- Use abstract classes when creating a family of closely related classes with common behavior or state.
- Interfaces allow for more flexible and loosely coupled designs.

Example:

// Use of interface for capability
interface Serializable {
    void serialize();
}

// Use of abstract class for shared behavior
abstract class Shape {
    private String color;

    Shape(String color) {
        this.color = color;
    }

    abstract void draw();
}