7. How do you use default methods in interfaces and what are the advantages of this feature in Java 8?

Advanced

7. How do you use default methods in interfaces and what are the advantages of this feature in Java 8?

Overview

Default methods were introduced in Java 8 as a means to add new functionalities to interfaces without breaking the classes that implement these interfaces. This feature helps in evolving interfaces over time without making major changes in the implementation classes, thus providing backward compatibility and flexibility in designing APIs.

Key Concepts

  1. Backward Compatibility: Default methods help in adding new methods to interfaces without affecting the existing implementations.
  2. Multiple Inheritance of Behavior: They allow an interface to provide a "default" implementation for methods, enabling a form of multiple inheritance.
  3. Functional Interfaces & Lambda Expressions: Default methods complement the introduction of lambda expressions in Java 8, enabling complex functional programming concepts.

Common Interview Questions

Basic Level

  1. What is a default method in an interface in Java 8?
  2. How do you define and use a default method in an interface?

Intermediate Level

  1. How do you resolve method conflicts when a class implements multiple interfaces that contain default methods with the same signature?

Advanced Level

  1. Discuss the impact of default methods on design patterns and API evolution.

Detailed Answers

1. What is a default method in an interface in Java 8?

Answer: A default method is a method in an interface that provides a specific implementation. This allows an interface to define methods that can have a body, which was not possible before Java 8. Classes that implement the interface can use the default method without providing an implementation.

Key Points:
- Allows adding new methods to interfaces without breaking existing implementations.
- Provides flexibility in interface design.
- Supports the enhancement of APIs without forcing all implementing classes to update.

Example:

public interface Vehicle {
    void start();

    // Default method
    default void turnAlarmOn() {
        System.out.println("The vehicle alarm is now on.");
    }
}

2. How do you define and use a default method in an interface?

Answer: To define a default method in an interface, use the default keyword followed by the method signature and its body. Classes implementing the interface can override the default method to provide a specific implementation or use the provided default implementation.

Key Points:
- Default methods are declared with the default keyword.
- Implementing classes can override default methods.
- Useful for adding new functionality to existing interfaces.

Example:

public interface Vehicle {
    void start();

    // Default method
    default void turnAlarmOn() {
        System.out.println("The vehicle alarm is now on.");
    }
}

public class Car implements Vehicle {
    public void start() {
        System.out.println("Car started.");
    }

    // Using the default implementation of turnAlarmOn
}

public class Bike implements Vehicle {
    public void start() {
        System.out.println("Bike started.");
    }

    // Overriding the default method
    @Override
    public void turnAlarmOn() {
        System.out.println("The bike alarm is now on.");
    }
}

3. How do you resolve method conflicts when a class implements multiple interfaces that contain default methods with the same signature?

Answer: When a class implements multiple interfaces with conflicting default methods (same signature), the class must override the conflicting method. Within the override, the class can choose to call a specific interface's default method using InterfaceName.super.methodName() syntax.

Key Points:
- Must override conflicting default methods in the implementing class.
- Use InterfaceName.super.methodName() to call a specific interface's default method.
- Resolves ambiguity by providing a clear path of implementation.

Example:

public interface FirstInterface {
    default void show() {
        System.out.println("FirstInterface's show");
    }
}

public interface SecondInterface {
    default void show() {
        System.out.println("SecondInterface's show");
    }
}

public class MyClass implements FirstInterface, SecondInterface {
    // Resolving method conflict by overriding
    @Override
    public void show() {
        FirstInterface.super.show(); // Choosing FirstInterface's version
    }
}

4. Discuss the impact of default methods on design patterns and API evolution.

Answer: Default methods have a significant impact on Java design patterns and API evolution. They enable interfaces to evolve while maintaining backward compatibility, allowing for more flexible and modular API development. In design patterns, default methods can simplify implementations by providing shared methods, thus reducing code duplication and promoting code reuse.

Key Points:
- Enhances interface evolution without breaking existing implementations.
- Simplifies the implementation of design patterns by providing shared functionalities directly in interfaces.
- Encourages modular programming by allowing interfaces to define behavior, not just contracts.

Example:

public interface Logger {
    void log(String message);

    // Default method added to the interface after its initial release
    default void logError(String error) {
        log("Error: " + error);
    }
}

// Implementing classes can benefit from the new default method without altering their code.