Interfaces in Java
By the Syncfusion DevTutorials team · Last updated
Describe abilities with interfaces: declare and implement them, implement several at once, add default and static methods, and use functional interfaces with lambdas.
Think about a wall socket.
Any device with the right plug can use it: a phone charger, a lamp, a fan. The socket does not care what the device is. It only cares that the plug has the right shape.
The socket is like a promise: "If you have this kind of plug, you can connect here."
In Java, an interface is that kind of promise. It lists the methods a class must have. Any class that keeps the promise can be used wherever the interface is expected.
In simple words: an interface says what a class can do, without saying how it does it.
What You Will Learn
In this lesson, you will learn:
- What an interface is, and why it is useful.
- How to declare an interface and its methods.
- How interface constants work.
- How a class implements an interface.
- How one class can implement several interfaces.
- How default and static methods add code to an interface.
- What a functional interface is, and how it works with lambdas.
- How interfaces compare with abstract classes.
Start With a Working Example
Press Run.
Three different classes keep the same promise
public class Main {
public static void main(String[] args) {
Notifier[] channels = {
new EmailNotifier(),
new SmsNotifier(),
new AppNotifier()
};
for (Notifier n : channels) {
n.send("Your order has shipped");
}
}
}
interface Notifier {
void send(String message);
}
class EmailNotifier implements Notifier {
public void send(String message) {
System.out.println("Email: " + message);
}
}
class SmsNotifier implements Notifier {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
class AppNotifier implements Notifier {
public void send(String message) {
System.out.println("App alert: " + message);
}
}
Expected output:
Email: Your order has shipped
SMS: Your order has shipped
App alert: Your order has shipped
The loop does not know or care which kind of notifier it has. It only knows that every Notifier has a send() method.
Try This
Write a fourth class, WhatsAppNotifier, that implements Notifier. Add it to the array. The loop needs no change.
Introduction to Interfaces
An interface is a type that lists methods a class must provide. It describes a capability, such as "can send a message" or "can be compared".
When a class implements an interface, it promises to write every one of those methods.
This gives you two big benefits:
- Swappable parts. Code that uses
Notifierworks with email, SMS or any future channel. You can switch one for another without touching that code. - Shared ability across unrelated classes. A
Carand aPhonehave nothing in common, but both can implementChargeable.
Think of a job advert that says "must be able to drive". It does not care who you are. It only cares that you have that ability.
Interface Declaration
You declare an interface with the interface keyword.
interface Shape {
double area();
double perimeter();
}
Interface names often describe an ability: Comparable, Runnable, Printable. Like classes, they use PascalCase.
You cannot create an object of an interface directly. new Shape() does not compile, because an interface has no full method bodies to run.
Interface Methods
A plain method in an interface has no body. It ends with a semicolon.
double area();
This is called an abstract method. It says "every class that implements me must write this".
Interface methods are automatically public and abstract. You do not need to write those words.
Interface Constants
An interface can hold fields. Every field in an interface is automatically public, static and final. In other words, every field is a constant.
Fields in an interface are shared constants
public class Main {
public static void main(String[] args) {
System.out.println("Max file size: " + Uploadable.MAX_SIZE_MB + " MB");
Photo p = new Photo(8);
Photo big = new Photo(40);
System.out.println("8 MB photo allowed? " + p.canUpload());
System.out.println("40 MB photo allowed? " + big.canUpload());
}
}
interface Uploadable {
int MAX_SIZE_MB = 25;
boolean canUpload();
}
class Photo implements Uploadable {
int sizeMb;
Photo(int sizeMb) {
this.sizeMb = sizeMb;
}
public boolean canUpload() {
return sizeMb <= MAX_SIZE_MB;
}
}
Expected output:
Max file size: 25 MB
8 MB photo allowed? true
40 MB photo allowed? false
MAX_SIZE_MB is a constant. You can read it as Uploadable.MAX_SIZE_MB, and Photo can use it directly because it implements the interface.
You cannot change it. Uploadable.MAX_SIZE_MB = 50; does not compile.
Interface Implementation
A class uses the implements keyword to keep an interface's promise.
The class must then write a body for every abstract method in the interface. If it misses one, it does not compile.
The methods must be public, because interface methods are public.
Each shape works out its own area
public class Main {
public static void main(String[] args) {
Shape[] shapes = { new Circle(7), new Square(5) };
for (Shape s : shapes) {
System.out.println(s.name() + " area: " + s.area());
}
}
}
interface Shape {
double area();
String name();
}
class Circle implements Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
public double area() {
return 3.14 * radius * radius;
}
public String name() {
return "Circle";
}
}
class Square implements Shape {
double side;
Square(double side) {
this.side = side;
}
public double area() {
return side * side;
}
public String name() {
return "Square";
}
}
Expected output:
Circle area: 153.86
Square area: 25.0
A Shape variable can hold a Circle or a Square. When you call s.area(), Java runs the version for that actual object.
Forgetting public on an implemented method is a very common error. Writing double area() without public gives attempting to assign weaker access privileges; was public.
Multiple Interface Implementation
A class can only have one parent class. But it can implement many interfaces. You separate them with commas.
class SmartPhone implements Camera, MusicPlayer, Phone { ... }
This is how Java lets one class have many abilities.
Think of a person who can drive, cook and swim. Each skill is separate, and one person can have all of them.
One class, three abilities
public class Main {
public static void main(String[] args) {
SmartPhone phone = new SmartPhone();
phone.call("98765 43210");
phone.takePhoto();
phone.play("Jai Ho");
Camera cam = phone;
cam.takePhoto();
}
}
interface Callable {
void call(String number);
}
interface Camera {
void takePhoto();
}
interface MusicPlayer {
void play(String song);
}
class SmartPhone implements Callable, Camera, MusicPlayer {
public void call(String number) {
System.out.println("Calling " + number);
}
public void takePhoto() {
System.out.println("Click! Photo saved.");
}
public void play(String song) {
System.out.println("Playing " + song);
}
}
Expected output:
Calling 98765 43210
Click! Photo saved.
Playing Jai Ho
Click! Photo saved.
SmartPhone keeps all three promises. So a SmartPhone can be stored in a Camera variable, a Callable variable or a MusicPlayer variable.
Through the Camera variable cam, only takePhoto() is visible. The variable's type decides which methods you can call.
A variable of an interface type can only call the methods that interface declares. In the example above, cam.call(...) would not compile, even though the object is a SmartPhone.
Default Methods
Since Java 8, an interface can contain a default method. A default method has a body. Classes that implement the interface get it for free.
You mark it with the default keyword.
A class can still write its own version of a default method if it needs different behaviour. This is called overriding it.
Why default methods exist: if you add a new abstract method to an interface that 100 classes already use, all 100 classes break. A default method adds new behaviour without breaking anyone.
A default method gives every class the same extra behaviour
public class Main {
public static void main(String[] args) {
Greeter english = new EnglishGreeter();
Greeter hindi = new HindiGreeter();
english.greetTwice("Asha");
hindi.greetTwice("Ravi");
}
}
interface Greeter {
String greet(String name);
default void greetTwice(String name) {
System.out.println(greet(name));
System.out.println(greet(name));
}
}
class EnglishGreeter implements Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}
class HindiGreeter implements Greeter {
public String greet(String name) {
return "Namaste, " + name;
}
public void greetTwice(String name) {
System.out.println(greet(name) + " (twice!)");
}
}
Expected output:
Hello, Asha
Hello, Asha
Namaste, Ravi (twice!)
EnglishGreeter did not write greetTwice(). It used the default version from the interface.
HindiGreeter wrote its own greetTwice(), which replaced the default.
Static Methods in Interfaces
An interface can also have static methods. They belong to the interface itself, like static methods in a class.
You call them with the interface name: InterfaceName.method().
Use them for helpers that belong with the interface, such as a method that checks or creates values.
A static helper that lives on the interface
public class Main {
public static void main(String[] args) {
System.out.println(Validator.isValidEmail("asha@mail.com"));
System.out.println(Validator.isValidEmail("asha.mail.com"));
System.out.println(Validator.isValidPin("560001"));
}
}
interface Validator {
static boolean isValidEmail(String email) {
return email.contains("@") && email.contains(".");
}
static boolean isValidPin(String pin) {
return pin.length() == 6;
}
}
Expected output:
true
false
true
No class implements Validator here. The static methods are called directly through the interface name.
Unlike default methods, static interface methods are not inherited by classes. You must always call them through the interface name.
Functional Interfaces
A functional interface is an interface with exactly one abstract method. It can still have default and static methods.
You can mark one with @FunctionalInterface. The compiler then checks that it really has only one abstract method.
Functional interfaces are special because you can implement them with a lambda expression. A lambda is a short way to write a method with no name:
(parameters) -> expression
Instead of writing a whole class, you write just the method's body.
Lambdas implement a one-method interface in one line
public class Main {
public static void main(String[] args) {
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
Calculator biggest = (a, b) -> a > b ? a : b;
System.out.println("Add: " + add.compute(6, 4));
System.out.println("Multiply: " + multiply.compute(6, 4));
System.out.println("Biggest: " + biggest.compute(6, 4));
}
}
@FunctionalInterface
interface Calculator {
int compute(int a, int b);
}
Expected output:
Add: 10
Multiply: 24
Biggest: 6
Each lambda becomes an object that implements Calculator. (a, b) -> a + b is the body of compute().
Java comes with many ready-made functional interfaces in java.util.function:
| Interface | Method | Takes | Returns | Example use |
|---|---|---|---|---|
Predicate<T> | test | One value | boolean | Is this number even? |
Function<T, R> | apply | One value | Another value | Turn a name into its length |
Consumer<T> | accept | One value | Nothing | Print a value |
Supplier<T> | get | Nothing | One value | Make a new default object |
Java's built-in functional interfaces
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Predicate<Integer> isAdult = age -> age >= 18;
Function<String, Integer> length = text -> text.length();
Consumer<String> shout = text -> System.out.println(text.toUpperCase() + "!");
System.out.println(isAdult.test(21));
System.out.println(length.apply("Chennai"));
shout.accept("welcome");
}
}
Expected output:
true
7
WELCOME!
The <Integer> and <String> parts say which types the interface works with. You will learn about these, called generics, in a later chapter.
Interfaces vs Abstract Classes
An abstract class is a class that cannot be created directly and may contain abstract methods. You will study it fully in the Abstraction lesson. Here is how it compares:
| Interface | Abstract class | |
|---|---|---|
| Keyword to use it | implements | extends |
| How many can a class use? | Many | Only one |
| Fields | Constants only (public static final) | Any fields, including ones that change |
| Constructors | No | Yes |
| Methods with bodies | default and static only | Any |
| Method access | public (or private helpers) | Any access level |
| Describes | What a class can do | What a class is |
| Example | Comparable, Runnable | Animal, Vehicle |
Easy Way to Remember: an interface is a can-do list. An abstract class is a half-built parent. Use an interface to share an ability. Use an abstract class to share code and fields between closely related classes.
Common mistakes
The following mistakes are common when writing and implementing interfaces. Each row shows what you see, why it happens and how to fix it.
| Symptom | Cause | Fix |
|---|---|---|
weaker access privileges; was public | An implemented method is not public | Add public |
does not override abstract method | A required method was not written | Write every abstract method |
is abstract; cannot be instantiated | new was used on an interface | Create an object of an implementing class |
no interface expected here | extends was used with an interface | Use implements |
cannot assign a value to final variable | An interface constant was changed | Treat interface fields as read-only |
cannot find symbol when calling a static interface method on an object | Static interface methods are not inherited | Call it as InterfaceName.method() |
What to Remember
- An interface lists methods a class promises to provide. It describes what a class can do.
- Interface methods with no body are abstract and
public. Interface fields are constants. - A class uses
implementsand must write every abstract method, markedpublic. - A class can implement many interfaces, but can extend only one class.
- Default methods give interfaces ready-made behaviour. Static methods are called through the interface name.
- A functional interface has exactly one abstract method and can be implemented with a lambda.
- Use an interface for a shared ability. Use an abstract class for shared code and fields.
Next: Inheritance