static and default methods in
interfaces provide a way to evolve interfaces over time while maintaining
backward compatibility. This feature, introduced in Java 8, allows you to add
new functionality to interfaces without breaking the existing implementations
of those interfaces.
Why Static and Default Methods are Beneficial for
Backward Compatibility:
- Default
Methods:
Ø
Adding Methods Without Breaking Existing
Code: Prior to Java 8, adding a new method to an interface meant that
all implementing classes would need to provide an implementation for that new
method, potentially breaking existing code. Default methods solve this by
providing a default implementation that existing classes can inherit without
any changes.
Ø
Enhancing Interfaces Over Time: As
your application evolves, you can add new default methods to an interface,
providing new functionality that can be used by existing and new
implementations alike.
Ø
Selective Overriding: Implementing
classes can override the default methods if they need a behavior different from
the provided default.
- Static
Methods:
Ø
Utility Methods in Interfaces: Static
methods in interfaces allow you to define utility or helper methods related to
the interface, which can be used without needing an instance of the
implementing class. This centralizes the logic related to the interface in one
place.
Ø
No Need for Utility Classes: Traditionally,
utility methods were placed in separate utility classes (e.g., Collections
class for collection-related methods). Static methods in interfaces reduce the
need for such utility classes by allowing these methods to be part of the
interface itself.
Example of Backward Compatibility:
java
package com.kartik.deflt.intrfce; public class Client { public static void main(String args[]){ Vehicle c=new Car(); c.getName(); System.out.println(c.turnAlarmOn()); System.out.println(c.turnAlarmOff()); Alarm a=new Car(); System.out.println(a.turnAlarmOn()); System.out.println(a.turnAlarmOff()); int sum=Alarm.sum(10, 20); System.out.println(sum); } } |
Java
package com.kartik.deflt.intrfce; public interface Alarm { default String turnAlarmOn() { return
"Turning the alarm on."; } default String turnAlarmOff() { return
"Turning the alarm off."; } static int sum(int a,int b){ return a+b; } } |
java
package com.kartik.deflt.intrfce; public interface Vehicle { void getName(); default String turnAlarmOn() { return
"Turning the alarm on for vehicle."; } default String turnAlarmOff() { return
"Turning the alarm off for vehicle."; } } |
Java
package com.kartik.deflt.intrfce; public class Car implements Alarm, Vehicle { @Override public String turnAlarmOn() { return
Vehicle.super.turnAlarmOn() + " " + Alarm.super.turnAlarmOn(); } @Override public String turnAlarmOff() { return
Vehicle.super.turnAlarmOff() + " " + Alarm.super.turnAlarmOff(); } @Override public void getName() { System.out.println("Kartik"); } } |
This Java code demonstrates how a class can implement
multiple interfaces and how default methods can be overridden or used from
those interfaces.
Breakdown:
- Alarm
Interface:
Ø
Contains two default methods: turnAlarmOn() and
turnAlarmOff(), which return strings indicating the alarm status.
Ø
Includes a static method sum(int a, int b) that
returns the sum of two integers.
- Vehicle
Interface:
Ø
Contains an abstract method getName(), which
must be implemented by any class that implements this interface.
Ø
Also has default methods turnAlarmOn() and
turnAlarmOff() with different messages compared to the Alarm interface.
- Car
Class:
Ø
Implements both Alarm and Vehicle interfaces.
Ø
Overrides the turnAlarmOn() and turnAlarmOff()
methods to combine the output from both interfaces using
Vehicle.super.turnAlarmOn() and Alarm.super.turnAlarmOn().
Ø
Implements the getName() method from the Vehicle
interface, printing "Kartik" when called.
- Client
Class (Main Method):
Ø
Creates an instance of Car and assigns it to
both Vehicle and Alarm references.
Ø
Calls the overridden turnAlarmOn() and
turnAlarmOff() methods, which return a combination of the messages from both
interfaces.
Ø
Demonstrates polymorphism by calling the methods
through both Vehicle and Alarm references.
Ø
Also demonstrates the usage of the static method
sum(int a, int b) from the Alarm interface.
Output:
When the main method in Client is executed, the output will
be:
plaintext
Kartik Turning the alarm on for vehicle. Turning the alarm on. Turning the alarm off for vehicle. Turning the alarm off. Turning the alarm on for vehicle. Turning the alarm on. Turning the alarm off for vehicle. Turning the alarm off. 30 |
Explanation:
Ø The
getName() method prints "Kartik".
Ø The
turnAlarmOn() and turnAlarmOff() methods in Car return combined messages from
both interfaces.
Ø The
sum() method from the Alarm interface adds two numbers and prints the result.
Conclusion:
Static and default methods are powerful tools for
maintaining backward compatibility while allowing interfaces to evolve. They
let you introduce new features and improvements without disrupting the existing
codebase, making them a valuable addition to the Java language.
static and default methods in interfaces |
0 Comments