SECTION 1
Historical Context & Motivation
Before Java existed, programmers working in languages like C and C++ struggled with a fundamental problem: how do you guarantee that unrelated classes share the same set of behaviors without forcing them into the same inheritance tree? C++ offered multiple inheritance, which allowed a class to extend more than one parent. While powerful, multiple inheritance introduced confusing bugs—most famously the diamond problem, where a class could inherit conflicting versions of the same method from two different parents.
When James Gosling and his team at Sun Microsystems designed Java in the early 1990s, they wanted a cleaner solution. They borrowed the concept of interfaces from languages like Objective-C's protocols. An interface defines what a class must do without specifying how it does it. This elegant idea became one of Java's most important features.
1979 • C++ Introduces Multiple Inheritance
1984 • Objective-C Protocols Emerge
1995 • Java 1.0 Launches with Interfaces
2014 • Java 8 Adds Default Methods
The central question that interfaces answer is this: how can you write code that works with any object that has certain capabilities—like being sortable, drawable, or serializable—without caring about the object's specific class? This is the power of programming to a contract rather than to a specific implementation.
SECTION 2
Core Principles & Definitions
An interface in Java is a reference type—similar to a class—that contains only abstract method signatures, constants, default methods, and static methods. Think of it as a contract or promise: any class that implements the interface must provide concrete code for every abstract method declared in that interface. If a class claims it implements an interface but fails to define even one required method, the compiler will refuse to build the program.
Interface = Contract
implements Keyword
implements keyword to sign the contract. The class must then provide method bodies for every abstract method in the interface.Multiple Interfaces
Polymorphism
Fields Are Constants
public static final. Interfaces define behavior, not mutable state.KEY TAKEAWAY
SECTION 3
Visual Explanation
draw(). The three solid boxes below—Circle, Square, and Triangle—each implement the interface, providing their own version of draw(). Dashed arrows point upward to indicate the "implements" relationship.In the diagram above, notice that the interface box uses a dashed border to distinguish it from concrete classes, which have solid borders. This is standard UML notation. Each class has its own fields (like radius for Circle), but all three classes share the draw() method because the interface requires it. The beauty of this design is that the rest of your program can work with any Drawable object without knowing whether it's a Circle, Square, or Triangle.
SECTION 4
How Interfaces Work in Code
Step 1: Declaring an Interface
You declare an interface using the interface keyword. Inside the curly braces, you list method signatures—no method bodies. By default, every method in an interface is public and abstract, so you don't need to write those modifiers explicitly (though you can if you want clarity). Here is a basic syntax pattern:
INTERFACE DECLARATION SYNTAX
The interface keyword replaces class. Methods have no curly braces—just a semicolon after the signature. Every method is implicitly public abstract.
Step 2: Implementing the Interface
A class signs the interface contract by using the implements keyword after the class name. The class must then provide a full method body for every abstract method in the interface. If you forget even one method, the Java compiler will produce an error.
IMPLEMENTATION SYNTAX
The @Override annotation is optional but strongly recommended—it tells the compiler you intend to fulfill a contract, helping catch typos in method names.
Step 3: Using Interface Types
One of the most powerful features is that you can declare variables using the interface type rather than the class type. For example, Drawable shape = new Circle(5.0); is perfectly valid. The variable shape can hold any object whose class implements Drawable. When you call shape.draw(), Java uses dynamic dispatch to call the correct version of draw() based on the actual object's class at runtime.
SECTION 5
Interface Syntax & Rules in Detail
Now that you understand the big picture, let's look more closely at the specific rules that govern interfaces in Java. These rules are enforced by the compiler, so violating any of them will prevent your program from compiling.
| Rule | What It Means | Code Example |
|---|---|---|
| Cannot be instantiated | You cannot write new Drawable(). Interfaces have no constructors. | // Drawable d = new Drawable(); ← ERROR |
| Methods are implicitly public abstract | You don't need to write public abstract before each method. | void draw(); // same as public abstract void draw(); |
| Fields are implicitly public static final | All variables in an interface are constants and must be initialized. | int MAX_SIZE = 100; // constant |
| A class can implement multiple interfaces | Separate interface names with commas after the implements keyword. | class Dog implements Drawable, Comparable<Dog> |
| An interface can extend another interface | Use extends (not implements) between interfaces. | interface Resizable extends Drawable { ... } |
| Implementing class must override ALL abstract methods | Unless the implementing class is itself declared abstract. | // Missing method body → compile error |
Key rules governing Java interfaces
Common Mistake
public in the class. The interface declares it as implicitly public, and Java does not allow you to reduce the visibility of an overridden method. Writing void draw() without public in your class gives it package-private access, which is more restrictive than public—and the compiler will reject it.SECTION 6
Worked Example: Building a Shape System
Let's build a complete example from scratch. We will define a Shape interface, create two classes that implement it, and then use polymorphism to process a collection of shapes.
Defining and Implementing the Shape Interface
- 1
Step 1 — Define the Interface
We create an interface calledShapewith two abstract methods:getArea()andgetPerimeter(). This contract says that any class implementing Shape must be able to calculate both its area and perimeter.public interface Shape { double getArea(); double getPerimeter(); } - 2
Step 2 — Implement Shape with Circle
TheCircleclass implementsShape. It stores aradiusfield and provides concrete method bodies for bothgetArea()(π × r²) andgetPerimeter()(2 × π × r).public class Circle implements Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double getArea() { return Math.PI * radius * radius; } @Override public double getPerimeter() { return 2 * Math.PI * radius; } } - 3
Step 3 — Implement Shape with Rectangle
TheRectangleclass also implementsShape. It haswidthandheightfields. Its formulas differ from Circle's, but the method signatures match the interface contract exactly.public class Rectangle implements Shape { private double width, height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public double getArea() { return width * height; } @Override public double getPerimeter() { return 2 * (width + height); } } - 4
Step 4 — Use Polymorphism in main()
In themainmethod, we create an array of typeShape[]. We can store both Circle and Rectangle objects in this array because they both implement Shape. We then loop through and callgetArea()on each—Java automatically calls the correct version.public class Main { public static void main(String[] args) { Shape[] shapes = { new Circle(5.0), new Rectangle(4.0, 6.0) }; for (Shape s : shapes) { System.out.println("Area: " + s.getArea()); } } } - 5
Step 5 — Verify Output
Running the program produces two lines. The Circle's area is π × 5² ≈ 78.54 and the Rectangle's area is 4 × 6 = 24.0. Java used dynamic dispatch to pick the rightgetArea()for each object.Area: 78.53981633974483 Area: 24.0
SECTION 7
Interfaces vs. Abstract Classes
Students often confuse interfaces with abstract classes because both can declare abstract methods. However, they serve different purposes and follow different rules. The table below highlights the key differences.
| Feature | Interface | Abstract Class |
|---|---|---|
| Methods | All methods are abstract by default (except default/static methods since Java 8) | Can have both abstract and fully implemented methods |
| Fields | Only constants (public static final) | Can have instance variables of any type and visibility |
| Constructors | No constructors allowed | Can have constructors (called by subclass constructors) |
| Multiple inheritance | A class can implement many interfaces | A class can extend only one abstract class |
| When to use | When unrelated classes need to share a behavior contract | When related classes share common code that you want to reuse |
Interface vs. Abstract Class comparison
KEY TAKEAWAY
SECTION 8
Connection to Advanced Interface Features
The basic interface you've learned today is the foundation, but Java has evolved interfaces significantly since version 8. Understanding what's ahead will help you appreciate why interfaces are designed the way they are.
| Feature | What You Learned Today | Advanced Version |
|---|---|---|
| Method bodies | Interfaces contain only abstract methods (no bodies) | Java 8+ allows default methods with full bodies inside interfaces |
| Static methods | Not covered in basic interfaces | Java 8+ interfaces can contain static utility methods |
| Functional interfaces | Interfaces with multiple methods | An interface with exactly one abstract method can be used with lambda expressions |
| Private methods | Not applicable | Java 9+ allows private helper methods inside interfaces |
Basic vs. Advanced Interface Features
As you progress in Java, you'll encounter interfaces like Comparable, Iterable, and Serializable that are built into the Java standard library. These interfaces power sorting algorithms, for-each loops, and data persistence. Mastering the basics you've learned today gives you the foundation to use and create all of these patterns confidently.
Looking Ahead
Comparable<T> interface frequently. It has a single method, compareTo(T other), and implementing it allows your objects to be sorted by Arrays.sort() and Collections.sort() automatically. This is the power of interfaces in action!SECTION 9
Practice Problems
Question 1: CONCEPTUAL
Show answer
draw() method, but nothing in the language connects them. You couldn't store both objects in a Drawable[] array or pass them to a method that accepts a Drawable parameter. The interface enables polymorphism: you can write a single method that works with any implementing class, and the compiler ensures no class forgets to implement a required method.Question 2: BASIC CALCULATION
public interface Measurable { double getMeasure(); }, write a complete class called BankAccount that implements Measurable. The class should have a balance field, a constructor, and getMeasure() should return the balance.Show answer
public class BankAccount implements Measurable { private double balance; public BankAccount(double balance) { this.balance = balance; } @Override public double getMeasure() { return balance; } }. Note three critical details: (1) the class header uses implements Measurable, (2) getMeasure() is declared public to match the interface's implicit public access, and (3) the @Override annotation is included for safety.Question 3: INTERMEDIATE
public interface Playable {
void play();
void pause();
}
public class Song implements Playable {
public void play() {
System.out.println("Playing song");
}
}Show answer
Song class implements Playable but only provides a body for play(). The pause() method is also required by the interface but is missing from the class. To fix this, the student must add public void pause() { System.out.println("Paused"); } to the Song class. The Java compiler enforces that every abstract method in an interface receives a concrete implementation in the class. Alternatively, the student could declare Song as abstract, but then it could not be instantiated.Question 4: APPLIED
Notifiable with methods sendNotification(String message) and getRecipient() (returns a String). Then write two implementing classes: EmailNotification and SMSNotification. Finally, write a method broadcastAll(Notifiable[] targets, String msg) that sends the same message to all targets.Show answer
public interface Notifiable { void sendNotification(String message); String getRecipient(); }. Then implement EmailNotification with an emailAddress field where sendNotification prints "Emailing [address]: [message]" and getRecipient returns the email. SMSNotification follows the same pattern with a phone number. The broadcastAll method uses a for-each loop: for (Notifiable n : targets) { n.sendNotification(msg); }. This demonstrates polymorphism—the method doesn't know or care whether each target is an email or SMS object.Question 5: CRITICAL THINKING
SmartPhone that implements three interfaces: Camera, Phone, and MusicPlayer. If both Camera and MusicPlayer declare a method void start(), does this cause a compilation error? Explain why or why not, and discuss how you would handle this situation in a real project.Show answer
void start() with the same signature and return type, the SmartPhone class provides a single start() implementation that satisfies both contracts simultaneously. Java treats identical abstract method signatures from different interfaces as one requirement. However, this creates a design problem: calling start() should it start the camera or the music player? In a real project, you would reconsider your interface design—perhaps renaming methods to startCamera() and startPlayback() to make the intent clear. If the return types differed (e.g., one returned void, the other returned boolean), the code would indeed fail to compile.SUMMARY
Lesson Summary
Summary
A Java interface is a reference type that defines a behavioral contract—a set of method signatures that any implementing class must provide. You declare an interface using the interface keyword, and a class adopts the contract using the implements keyword. All methods in an interface are implicitly public and abstract, and all fields are implicitly public static final (constants). Unlike class inheritance, a single class can implement multiple interfaces.
The true power of interfaces lies in polymorphism: you can use an interface type as a variable, parameter, or array type, and any object whose class implements that interface can fill that role. At runtime, Java's dynamic dispatch calls the correct method implementation based on the actual object's class. This allows you to write flexible, reusable code that works with any present or future class that fulfills the contract. Interfaces differ from abstract classes primarily in that they cannot hold instance variables or constructors, and a class can implement many interfaces but extend only one class.