- Static and Default Methods in Interfaces in Java
- 1. Overview
- Further reading:
- Private Methods in Java Interfaces
- Using an Interface vs. Abstract Class in Java
- A Guide to the Static Keyword in Java
- 2. Why Interfaces Need Default Methods
- 3. Default Interface Methods in Action
- 4. Multiple Interface Inheritance Rules
- 5. Static Interface Methods
- 6. Conclusion
Static and Default Methods in Interfaces in Java
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
We rely on other people’s code in our own work. Every day.
It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.
The problem is, of course, when things fall apart in production — debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky.
Lightrun is a new kind of debugger.
It’s one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics.
Learn more in this quick, 5-minute Lightrun tutorial:
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:
DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema.
The way it does all of that is by using a design model, a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.
And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
We’re looking for a new Java technical editor to help review new articles for the site.
1. Overview
Java 8 brought a few brand new features to the table, including lambda expressions, functional interfaces, method references, streams, Optional, and static and default methods in interfaces.
We’ve already covered a few of these features in another article. Nonetheless, static and default methods in interfaces deserve a deeper look on their own.
In this tutorial, we’ll learn how to use static and default methods in interfaces, and discuss some situations where they can be useful.
Further reading:
Private Methods in Java Interfaces
Learn how to define private methods within an interface and how we can use them from both static and non-static contexts.
Using an Interface vs. Abstract Class in Java
A Guide to the Static Keyword in Java
2. Why Interfaces Need Default Methods
Like regular interface methods, default methods are implicitly public; there’s no need to specify the public modifier.
Unlike regular interface methods, we declare them with the default keyword at the beginning of the method signature, and they provide an implementation.
Let’s look at a simple example:
public interface MyInterface < // regular interface methods default void defaultMethod() < // default method implementation >>
The reason why the Java 8 release included default methods is pretty obvious.
In a typical design based on abstractions, where an interface has one or multiple implementations, if one or more methods are added to the interface, all the implementations will be forced to implement them too. Otherwise, the design will just break down.
Default interface methods are an efficient way to deal with this issue. They allow us to add new methods to an interface that are automatically available in the implementations. Therefore, we don’t need to modify the implementing classes.
In this way, backward compatibility is neatly preserved without having to refactor the implementers.
3. Default Interface Methods in Action
To better understand the functionality of default interface methods, let’s create a simple example.
Suppose we have a naive Vehicle interface and just one implementation. There could be more, but let’s keep it that simple:
public interface Vehicle < String getBrand(); String speedUp(); String slowDown(); default String turnAlarmOn() < return "Turning the vehicle alarm on."; >default String turnAlarmOff() < return "Turning the vehicle alarm off."; >>
Now let’s write the implementing class:
public class Car implements Vehicle < private String brand; // constructors/getters @Override public String getBrand() < return brand; >@Override public String speedUp() < return "The car is speeding up."; >@Override public String slowDown() < return "The car is slowing down."; >>
Finally, let’s define a typical main class, which creates an instance of Car and calls its methods:
public static void main(String[] args)
Please notice how the default methods, turnAlarmOn() and turnAlarmOff(), from our Vehicle interface are automatically available in the Car class.
Furthermore, if at some point we decide to add more default methods to the Vehicle interface, the application will still continue working, and we won’t have to force the class to provide implementations for the new methods.
The most common use of interface default methods is to incrementally provide additional functionality to a given type without breaking down the implementing classes.
In addition, we can use them to provide additional functionality around an existing abstract method:
4. Multiple Interface Inheritance Rules
Default interface methods are a pretty nice feature, but there are some caveats worth mentioning. Since Java allows classes to implement multiple interfaces, it’s important to know what happens when a class implements several interfaces that define the same default methods.
To better understand this scenario, let’s define a new Alarm interface and refactor the Car class:
public interface Alarm < default String turnAlarmOn() < return "Turning the alarm on."; >default String turnAlarmOff() < return "Turning the alarm off."; >>
With this new interface defining its own set of default methods, the Car class would implement both Vehicle and Alarm:
public class Car implements Vehicle, Alarm < // . >
In this case, the code simply won’t compile, as there’s a conflict caused by multiple interface inheritance (a.k.a the Diamond Problem). The Car class would inherit both sets of default methods. So which ones should we call?
To solve this ambiguity, we must explicitly provide an implementation for the methods:
@Override public String turnAlarmOn() < // custom implementation >@Override public String turnAlarmOff() < // custom implementation >
We can also have our class use the default methods of one of the interfaces.
Let’s see an example that uses the default methods from the Vehicle interface:
@Override public String turnAlarmOn() < return Vehicle.super.turnAlarmOn(); >@Override public String turnAlarmOff()
Similarly, we can have the class use the default methods defined within the Alarm interface:
@Override public String turnAlarmOn() < return Alarm.super.turnAlarmOn(); >@Override public String turnAlarmOff()
It’s even possible to make the Car class use both sets of default methods:
@Override public String turnAlarmOn() < return Vehicle.super.turnAlarmOn() + " " + Alarm.super.turnAlarmOn(); >@Override public String turnAlarmOff()
5. Static Interface Methods
In addition to declaring default methods in interfaces, Java 8 also allows us to define and implement static methods in interfaces.
Since static methods don’t belong to a particular object, they’re not part of the API of the classes implementing the interface; therefore, they have to be called by using the interface name preceding the method name.
To understand how static methods work in interfaces, let’s refactor the Vehicle interface and add a static utility method to it:
Defining a static method within an interface is identical to defining one in a class. Moreover, a static method can be invoked within other static and default methods.
Let’s suppose that we want to calculate the horsepower of a given vehicle’s engine. We just call the getHorsePower() method:
Vehicle.getHorsePower(2500, 480));
The idea behind static interface methods is to provide a simple mechanism that allows us to increase the degree of cohesion of a design by putting together related methods in one single place without having to create an object.
The same can pretty much be done with abstract classes. The main difference is that abstract classes can have constructors, state, and behavior.
Furthermore, static methods in interfaces make it possible to group related utility methods, without having to create artificial utility classes that are simply placeholders for static methods.
6. Conclusion
In this article, we explored in depth the use of static and default interface methods in Java 8. At first glance, this feature may look a little bit sloppy, particularly from an object-oriented purist perspective. Ideally, interfaces shouldn’t encapsulate behavior, and we should only use them for defining the public API of a certain type.
When it comes to maintaining backward compatibility with existing code, however, static and default methods are a good trade-off.
As usual, all the code samples shown in this article are available over on GitHub.
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes: