Java Interfaces
Java - Interfaces
Section titled “Java - Interfaces”In Java, an interface is a reference type, similar to a class, that defines a contract. It specifies a set of abstract methods that implementing classes must provide. Since Java 8, interfaces can also contain default methods, static methods, and even private methods (since Java 9).
Think of an interface like a blueprint for capabilities. A class implements an interface, promising to provide the functionality defined in that interface’s contract.
Key characteristics of Java interfaces:
Section titled “Key characteristics of Java interfaces:”- Cannot be instantiated directly.
- Can contain abstract methods (no implementation, implicitly
public abstract). - Can contain
defaultmethods (introduced in Java 8): Provide a default implementation that implementing classes inherit. This allows adding new methods to interfaces without breaking existing implementations. - Can contain
staticmethods (introduced in Java 8): Utility methods associated with the interface itself, not with any implementing object. - Can contain
privatemethods (introduced in Java 9): Helper methods for default or static methods within the interface. - Can contain
public static finalconstants (fields). All fields are implicitlypublic,static, andfinal. - A class can implement multiple interfaces.
- An interface can extend multiple other interfaces.
Why Use Interfaces?
Section titled “Why Use Interfaces?”- Achieve Abstraction: Hide implementation details, exposing only the necessary behavior.
- Achieve Multiple Inheritance of Type: A class can implement multiple interfaces, inheriting different sets of capabilities.
- Loose Coupling: Code depends on the interface contract, not specific implementations, making systems more flexible and maintainable.
- Polymorphism: Objects can be treated as instances of an interface type they implement.
- API Definition: Define clear contracts for libraries and frameworks.
Declaring Interfaces
Section titled “Declaring Interfaces”Use the interface keyword to declare an interface. File name must match the interface name (e.g., Vehicle.java).
Modern Interface Example:
Section titled “Modern Interface Example:”/* FileName: Vehicle.java */
/** * Defines basic capabilities for vehicles. */public interface Vehicle {
// Constant (implicitly public static final) String TYPE = "Generic Vehicle";
// Abstract method (implicitly public abstract) void startEngine();
void stopEngine();
// Default method (Java 8+) default void honk() { System.out.println("Beep beep!"); log("Honk executed"); // Using private helper method }
// Static method (Java 8+) static void displayType() { System.out.println("This is a type of: " + TYPE); }
// Private method (Java 9+) - Helper for default/static methods private void log(String message) { System.out.println("LOG: " + message); }}Implementing Interfaces
Section titled “Implementing Interfaces”A class uses the implements keyword to implement one or more interfaces. If a class implements an interface but does not provide an implementation for all abstract methods, the class itself must be declared abstract.
Use the @Override annotation when implementing interface methods for compile-time checks and clarity.
Example Implementation:
Section titled “Example Implementation:”/* FileName: Car.java */
public class Car implements Vehicle {
private boolean engineRunning = false;
@Override public void startEngine() { engineRunning = true; System.out.println("Car engine started."); }
@Override public void stopEngine() { engineRunning = false; System.out.println("Car engine stopped."); }
// Optional: Override the default method @Override public void honk() { System.out.println("HONK HONK! (Car specific)"); }
public boolean isEngineRunning() { return engineRunning; }
public static void main(String[] args) { // Using the static method from the interface Vehicle.displayType();
Car myCar = new Car(); myCar.startEngine(); myCar.honk(); // Calls the overridden honk method myCar.stopEngine();
// Polymorphism: Treat Car as a Vehicle Vehicle anotherVehicle = new Car(); anotherVehicle.startEngine(); // anotherVehicle.isEngineRunning(); // Error: isEngineRunning() is not in Vehicle interface
// Example using the default honk if not overridden Vehicle bike = new Motorbike(); // Assuming Motorbike implements Vehicle but doesn't override honk bike.startEngine(); bike.honk(); // Calls the default honk() from Vehicle interface bike.stopEngine(); }}
// Assume Motorbike class exists and implements Vehicle without overriding honk/*class Motorbike implements Vehicle { @Override public void startEngine() { System.out.println("Motorbike engine started."); } @Override public void stopEngine() { System.out.println("Motorbike engine stopped."); }}*/Key Rules for Implementation:
Section titled “Key Rules for Implementation:”- A class must implement all abstract methods defined in the interface(s) it implements, or the class must be declared abstract.
- The implementing method must have the same signature (name, parameter types) and a compatible return type (same or a subtype).
- The implementing method cannot have a more restrictive access modifier (e.g., if the interface method is
public, the implementation must also bepublic). - Use the
@Overrideannotation. - A class can implement multiple interfaces by listing them after the
implementskeyword, separated by commas (e.g.,class MyClass implements InterfaceA, InterfaceB).
Extending Interfaces
Section titled “Extending Interfaces”An interface can inherit from other interfaces using the extends keyword. This allows creating hierarchies of interfaces. A child interface inherits all abstract methods, default methods, static methods, and constants from its parent interface(s).
Example: Extending Interfaces
Section titled “Example: Extending Interfaces”// Filename: ElectricVehicle.javapublic interface ElectricVehicle extends Vehicle { // Extends Vehicle void charge(); int getBatteryLevel();}
// Filename: Autonomous.javapublic interface Autonomous { void driveAutonomously();}
// Filename: AutonomousElectricCar.java// Implementing class needs to implement methods from ElectricVehicle, Vehicle, and Autonomouspublic class AutonomousElectricCar implements ElectricVehicle, Autonomous {
@Override public void startEngine() { /* Implementation */ System.out.println("Electric motor started."); }
@Override public void stopEngine() { /* Implementation */ System.out.println("Electric motor stopped."); }
@Override public void charge() { /* Implementation */ System.out.println("Charging..."); }
@Override public int getBatteryLevel() { /* Implementation */ return 85; }
@Override public void driveAutonomously() { /* Implementation */ System.out.println("Driving autonomously."); }
// It can still use default/static methods from Vehicle, e.g., honk()}Interfaces vs. Abstract Classes
Section titled “Interfaces vs. Abstract Classes”With the addition of default methods, interfaces can provide implementation, blurring the lines with abstract classes. However, key differences remain:
- Multiple Inheritance: A class can implement multiple interfaces but extend only one abstract class.
- State (Instance Variables): Abstract classes can have instance variables (state), while interfaces traditionally cannot (only
public static finalconstants). - Constructors: Abstract classes can have constructors, interfaces cannot.
- Purpose: Use an abstract class when you want to provide a common base implementation and state for a group of related subclasses (an “is-a” relationship). Use an interface when you want to define a contract or capability that various, possibly unrelated, classes can implement (a “has-a” or “can-do” relationship).
Functional Interfaces
Section titled “Functional Interfaces”A functional interface is an interface that contains exactly one abstract method (though it can have multiple default or static methods). They are crucial for enabling functional programming in Java using lambda expressions and method references (e.g., Runnable, Comparator, ActionListener).
The @FunctionalInterface annotation can be used to indicate this intent and allow the compiler to verify it.
Example:
Section titled “Example:”@FunctionalInterfaceinterface MyFunctionalInterface { void execute(); // Single abstract method
default void print() { System.out.println("Printing from functional interface."); }}
// Usage with Lambda:MyFunctionalInterface runner = () -> System.out.println("Executing lambda.");runner.execute(); // Output: Executing lambda.runner.print(); // Output: Printing from functional interface.Further Learning:
Section titled “Further Learning:”Explore the Java documentation for core interfaces like List, Map, Set, Comparable, Runnable, and Callable to see practical examples.