What is Java Interface?
A Java interface is a blueprint or guide for a class. It lists methods that a class must have, but it does not say how those methods should work. It also defines unchanging values. Classes then implement these interfaces, which means they promise to follow the rules set by the interface.
You use the word interface
to tell Java you are making an interface. An interface mostly tells you what a class should do, rather than how the class will do it.
public interface Printable {
void print(); // This is a method that classes must implement
int PAGE_LIMIT = 100; // This is a constant value
}
This example interface, Printable
, makes sure that any class using it will have a method named print()
. It also gives a constant value, PAGE_LIMIT
, which is set to 100.
Why Interfaces are Important?
Interfaces offer many good things that help you build strong and adaptable Java applications. They are very useful for designing your programs.
- Make Code Abstract: Interfaces hide the small details of how something works. You only see what methods are available. This makes your code simpler to use because you do not need to know the inner workings.
- Allow Multiple Behaviors: Java does not let a class inherit from more than one class. However, interfaces let a single class act like it has many different kinds of behaviors. This is a very powerful way to design your programs.
- Help with Loose Connections: Interfaces make parts of your code connect loosely. This means that classes depend on the rules defined by interfaces, not on specific ways things are built. This makes your code much more flexible and easier to change later.
- Set Rules for APIs: Interfaces create clear rules for how different parts of a program or different programs will talk to each other, like a contract. Developers then know exactly what methods they can expect to use. This helps many people work together on the same project more easily.
Learn Java the right way! Our course teaches you essential programming skills, from coding basics to complex projects, setting you up for success in the tech industry.
How to Make an Interface
Making an interface is quite simple. You just use the word interface
before its name.
public interface MyInterface {
void doSomething(); // This method must be public and abstract
String getData(); // This method must also be public and abstract
}
All methods you put in an interface are automatically public and abstract. This means anyone can use them, and they do not have a body or code inside them. Also, any variables you put in an interface are automatically public, static, and final.
This means they are constant values that belong to the interface itself, not to an object of the interface. You do not need to add these keywords yourself; Java adds them for you.
How to Use an Interface in a Class
A class uses an interface by adding the word implements
followed by the interface’s name. The class then must write the code for all the methods that the interface said it should have.
Here is an example of how a Document
class uses the Printable
interface:
public class Document implements Printable {
@Override
public void print() { // This method provides the actual code for print()
System.out.println("Printing document...");
}
}
You must include the @Override
tag and write the code for the print()
method inside the Document
class. If you do not provide code for all the methods from the interface, the Java compiler will show an error.
A single class can use more than one interface. You just list them with commas in between their names.
public class Report implements Printable, Exportable {
// This class must write code for methods from both Printable and Exportable interfaces.
@Override
public void print() {
System.out.println("Printing report...");
}
@Override
public void export() {
System.out.println("Exporting report...");
}
}
Abstract Classes Versus Interfaces
People sometimes get abstract classes and interfaces mixed up. However, they are used for different things.
Here is a table that shows the main differences between them:
Abstract Class | Interface | |
---|---|---|
What It Is | A class that cannot be directly created as an object and can contain abstract methods (methods without a body). | A blueprint for a class that contains only abstract methods (before Java 8) and constant variables. |
Methods | Can have methods with code and methods without code. | Can only have methods without code (before Java 8). After Java 8, can also have methods with default code, static methods, and private methods. |
Variables | Can have variables that belong to an object and variables that belong to the class. | Can only have unchanging values that are public, static, and final. |
Constructors | Can have special methods to create objects (constructors). | Cannot have special methods to create objects (constructors). |
Inheritance | A class can only extend one abstract class. | A class can implement many interfaces. |
Main Goal | Gives a common base for classes that are related to each other. | Defines a set of actions or behaviors that classes must follow. |
Access Types | Methods and variables can have different access levels, like public, private, protected. | Methods are always public. |
Newer Features for Interfaces (Java 8 and Later)
Java versions 8 and newer added new features to interfaces. These changes make interfaces more powerful for developers. They help you reuse code and write less repeated code.
Default Methods
Default methods provide some ready-made code inside the interface itself. Classes that use this interface can use these methods as they are, or they can write their own version of these methods. This is very helpful when you want to add a new method to an interface without forcing all existing classes that use it to change their code.
public interface Logger {
void log(String message); // An abstract method that must be implemented
default void logInfo(String message) { // This is a default method with code
log("INFO: " + message); // It uses the abstract log method
}
default void logError(String message) { // Another default method
log("ERROR: " + message);
}
}
public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println(message); // This class implements the abstract log method
}
}
// How to use it:
ConsoleLogger logger = new ConsoleLogger();
logger.logInfo("User logged in."); // This uses the default implementation from the interface
Static Methods
Interfaces can also have static methods. You call static methods directly on the interface itself, not on an object of a class that implements the interface. These methods are useful for common helper tasks that are related to the interface’s purpose.
public interface MathUtils {
static int add(int a, int b) { // A static method in the interface
return a + b;
}
static int subtract(int a, int b) { // Another static method
return a - b;
}
}
// How to call it directly:
int sum = MathUtils.add(5, 3);
System.out.println("Sum: " + sum); // This will print: Sum: 8
Private Methods (Java 9 and later)
Starting with Java 9, you can add private methods to interfaces. These methods are helper methods that only other methods within the same interface (like default or static methods) can use. They help you organize your code better inside the interface by letting you put common helper logic in one place.
public interface Validator {
private boolean isValidString(String s) { // This is a private helper method
return s != null && !s.trim().isEmpty(); // Checks if a string is not null and not empty
}
default void validateName(String name) { // A default method that uses the private helper
if (!isValidString(name)) {
throw new IllegalArgumentException("Name cannot be empty.");
}
System.out.println("Name is valid: " + name);
}
default void validateEmail(String email) { // Another default method
if (!isValidString(email) || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email format.");
}
System.out.println("Email is valid: " + email);
}
}
// How to use it:
// We create an anonymous implementation for demonstration purposes.
Validator myValidator = new Validator() {};
myValidator.validateName("John Doe"); // This will print: Name is valid: John Doe
// If you uncomment the line below, it will throw an error:
// myValidator.validateName("");
Good Ways to Use Interfaces
Follow these tips to use interfaces in the best way possible.
- Make Interfaces Small: Design each interface to do one specific job. Avoid making very large interfaces that try to do too many things. Smaller interfaces are easier to understand and use.
- Give Interfaces Clear Names: Choose names that clearly describe what the interface does. Often, names that end with “-able” (like
Printable
) or “-er” (likeLogger
) are good choices. - Use Interfaces for Callbacks: Interfaces are excellent for setting up “callbacks.” This is when one part of your code needs another part to do something specific without knowing exactly what that other part is. This helps keep your code loosely connected.
- Choose Composition Over Inheritance: Often, it is better to use interfaces with composition (where one object contains another object) instead of only using inheritance (where one class gets properties from another). This makes your code more flexible and easier to reuse in different situations.
Real-World Examples
You can find interfaces in many parts of Java’s built-in libraries and other frameworks.
java.lang.Runnable
: This interface has just one method, run()
. You use it to define a task that a separate thread (a lightweight part of a program) can carry out. For example, when you want to run code in the background without freezing your main program, you would put that code inside a Runnable
.
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("This task is now running in a new thread.");
}
}
// How to use it to start a new thread:
Thread thread = new Thread(new MyTask());
thread.start(); // This starts the new thread, running MyTask's run() method.
java.util.List
: This interface sets the rules for collections of items that have an order. Specific types of lists, like ArrayList
and LinkedList
, then provide the actual ways to store and manage these ordered items. You can write code that works with any type of List
because they all follow the List
interface’s rules.
import java.util.ArrayList;
import java.util.List;
List<String> names = new ArrayList<>(); // ArrayList implements the List interface
names.add("Alice");
names.add("Bob");
System.out.println("Names in the list: " + names);
java.awt.event.ActionListener
: In programs with graphical user interfaces (GUIs), this interface is very important for handling things a user does, like clicking a button. When a user clicks a button, the actionPerformed()
method from the ActionListener
is called to react to that click.
import javax.swing.*; // Used for GUI elements
import java.awt.event.ActionEvent; // Represents an action event
import java.awt.event.ActionListener; // The interface for listening to actions
public class MyButtonApp {
public static void main(String[] args) {
JFrame frame = new JFrame("Button Example"); // Creates a window
JButton button = new JButton("Click Me"); // Creates a button
button.addActionListener(new ActionListener() { // Attaches an action listener to the button
@Override
public void actionPerformed(ActionEvent e) { // This code runs when the button is clicked
JOptionPane.showMessageDialog(frame, "The button was clicked!");
}
});
frame.add(button); // Adds the button to the window
frame.setSize(300, 200); // Sets the window size
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // What happens when you close the window
frame.setVisible(true); // Makes the window appear
}
}
Understanding these examples helps you truly see how powerful interfaces can be in real programs.
How Interfaces Might Affect Performance
While interfaces offer great benefits for designing your code, it is good to know a little about how they might affect how fast your program runs. When you call a method using a variable that is an interface type, Java has to figure out which specific version of that method to call at the exact moment the program runs.
This process is called dynamic dispatch. It can add a very small amount of time compared to calling a method directly on a known class. For most applications, this tiny delay is not important. However, in very fast systems where every millisecond counts and you make many, many interface calls, it is something to consider. Modern Java systems are very good at making this process fast, so it usually does not cause problems.
Conclusion
Interfaces are a very basic and important part of programming in Java. They help you make your code more abstract, more flexible, and easier to reuse. You should use them to define clear rules for your classes. They are essential for building software systems that you can easily change and keep up-to-date in the future.
Try this example yourself:
Let’s make an interface called Shape
that has a method to get its area. Then, create two classes, Circle
and Rectangle
, that both use the Shape
interface. Each class will provide its own way to calculate its area.
// Step 1: Define the Shape interface. This sets the rule that every Shape must have a getArea() method.
public interface Shape {
double getArea(); // This method will return the area of the shape.
}
// Step 2: Create the Circle class, which uses the Shape interface.
public class Circle implements Shape {
private double radius; // A circle needs a radius to calculate its area.
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() { // This is how a Circle calculates its area.
return Math.PI * radius * radius;
}
}
// Step 3: Create the Rectangle class, which also uses the Shape interface.
public class Rectangle implements Shape {
private double width; // A rectangle needs a width.
private double height; // And it needs a height.
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double getArea() { // This is how a Rectangle calculates its area.
return width * height;
}
}
// Step 4: Test your implementations. This main class will create objects of Circle and Rectangle
// and use their getArea() methods through the Shape interface.
public class ShapeCalculator {
public static void main(String[] args) {
Shape circle = new Circle(5.0); // We create a Circle object but store it as a Shape.
System.out.println("The area of the Circle is: " + circle.getArea());
Shape rectangle = new Rectangle(4.0, 6.0); // We create a Rectangle object but store it as a Shape.
System.out.println("The area of the Rectangle is: " + rectangle.getArea());
}
}