Java Interfaces
Complete Notes + Interview Q&A
OOPs | JDK 8 & 9 Features | Functional Interfaces | Lambda Expressions
Section 1 — Interface Basics
What is an Interface?
• Definition: Up to JDK 1.7:
• An interface is a collection of pure abstract methods.
• From JDK 1.8+: An interface is a collection of abstract methods AND concrete methods, used
for standardization.
• All methods are automatically public and abstract unless marked default, static, or private.
• An interface cannot be instantiated — no objects can be created directly from it.
Two Primary Purposes
Purpose Explanation
Standardization Every UPI app (PhonePe, GPay, Paytm) uses the
same payment interface — same methods, same
behavior, enforced by the interface.
Multiple inheritance A class can implement multiple interfaces
simultaneously. Example: String implements
Comparable, Serializable, and CharSequence.
Real-World Example — Payment Gateway
Every UPI payment app has the same core behavior. The interface enforces this standard:
interface PaymentGateway {
void transferMoney(); // abstract (automatically)
void processPayment(); // abstract (automatically)
}
class PhonePe implements PaymentGateway {
public void transferMoney() { [Link]("PhonePe transferring"); }
public void processPayment() { [Link]("PhonePe processing"); }
}
class RazorPay implements PaymentGateway {
public void transferMoney() { [Link]("RazorPay transferring"); }
public void processPayment() { [Link]("RazorPay processing"); }
}
// Loose coupling via upcasting (Polymorphism)
PaymentGateway pp = new PhonePe(); // interface type as reference
PaymentGateway rp = new RazorPay();
Tip: Always use the interface type as the reference variable (loose coupling). This is upcasting and
enables polymorphism.
Override Rules (same as Inheritance)
• The implementing class must use public — removing it reduces visibility (compile error:
'decreasing visibility').
• Return type and parameter list must exactly match the interface method signature.
• All abstract methods must be overridden, or the class itself must be declared abstract.
• If you give a parameter in the overriding method that doesn't match — it becomes a new
method, not an override. Remove @Override or the class will have a compile error.
Interface vs Abstract Class
Interface Abstract Class
Used for standardization Used for partial implementation
Supports multiple inheritance Only single inheritance
Methods: public by default Methods: any access modifier
Cannot have constructors Can have constructors
From JDK8: can have concrete methods Always allowed concrete methods
Interview answer: If JDK8 gives interfaces concrete methods, why not just use abstract class?
Answer: (1) Interfaces support multiple inheritance. (2) Interfaces enforce standardization more
strictly.
Section 2 — JDK 8 & 9 Features in Interfaces
All Method Types Allowed in an Interface
Method type Version / Purpose
abstract void m(); Always — must be overridden by implementing
class
default void m() { } JDK 8 — backward compatibility (inherited by all)
static void m() { } JDK 8 — interface-only access, not inherited
private void m() { } JDK 9 — reduce redundancy in default methods
private static void m() { } JDK 9 — reduce redundancy in static methods
Default Methods (JDK 8)
• A concrete method with a body inside an interface.
• Purpose: backward compatibility — add new features to an interface without breaking existing
implementing classes.
• All implementing classes inherit the default method automatically (no override required).
• Can be overridden in implementing class if custom behavior is needed.
• Cannot be placed inside a regular class (compile error: 'Default methods are allowed only in
interfaces').
interface PaymentGateway {
void transferMoney(); // abstract
void processPayment(); // abstract
// NEW feature — all classes get this automatically
default void refundPayment() {
[Link]("Refund under process");
}
}
// PhonePe, RazorPay, Paytm all inherit refundPayment() FREE
// No need to change any existing implementing class
Analogy: Like an Android OS update — new features (Android 17) are added without breaking old
ones (camera still works). Old features remain 'backward compatible'.
Static Methods (JDK 8)
• A concrete method with body, accessible ONLY via the interface name.
• NOT inherited by implementing classes (unlike default methods).
• Purpose: utility methods that belong to the interface itself, not to implementing classes.
interface PaymentGateway {
static void display() {
[Link]("Payment gateway is working");
}
}
[Link](); // Correct
[Link](); // ERROR - not inherited
[Link](); // ERROR - not inherited
Error message: 'The static method display() from interface PaymentGateway can only be accessed
using the interface type'
Private Methods (JDK 9)
• Purpose: reduce code redundancy inside the interface itself.
• private void: called from default methods inside the interface.
• private static void: called from static methods inside the interface.
• Neither is accessible outside the interface.
• Key rule: a static method cannot call a non-static private method (error: 'non-static method
cannot be referenced from static context') — hence private static is needed.
interface PaymentGateway {
// Reduces redundancy — used by default method
private static void log(String message) {
[Link]("Gateway log: " + message);
}
default void refundPayment() {
log("Refund initiated"); // reuse — no duplication
log("Refund in progress");
log("Refund completed");
}
}
Section 3 — Functional Interface (JDK 8)
What is a Functional Interface?
• An interface that has exactly ONE abstract method.
• Can have any number of default, static, private, or private static methods.
• Annotated with @FunctionalInterface — the compiler then enforces the one-abstract-method
rule.
• If you add a second abstract method with @FunctionalInterface, you get a compile error.
@FunctionalInterface
interface Display {
void display(); // exactly ONE abstract method
default void show() { } // allowed
static void info() { } // allowed
private void helper() { } // allowed (JDK9)
}
Built-in Functional Interface Examples
Interface Abstract method + Usage
Runnable run() — used in multithreading to define tasks
Comparable<T> compareTo() — used in String for lexicographic
comparison (String implements Comparable)
Comparator<T> compare() — used for custom sorting logic
Key interview fact: String class internally implements Comparable, Serializable, and CharSequence
— this is a real example of multiple interface implementation!
4 Ways to Implement a Functional Interface
Way 1 — Regular Class (least encapsulated)
class Gamma implements Display {
public void display() {
[Link]("Hello from regular class");
}
}
Display d = new Gamma(); // polymorphism — interface as reference
[Link]();
Way 2 — Inner Class (more encapsulated)
A class defined inside another class. The implementing class is nested inside the outer class, reducing
its visibility.
class Outer {
class Gamma implements Display {
public void display() {
[Link]("Hello from inner class");
}
}
public static void main(String[] args) {
Display d = new Gamma();
[Link]();
}
}
Way 3 — Anonymous Inner Class (highly encapsulated)
A class without a name, defined and instantiated in a single expression. No separate class declaration
needed.
Display d = new Display() { // 'new' + interface name + { body }
public void display() {
[Link]("Hello from anonymous inner class");
}
}; // semicolon ends the whole expression
[Link]();
Way 4 — Lambda Expression (most concise, JDK 8)
The most expressive way. No class name, no method name — just the body.
Display d = () -> [Link]("Hello from lambda");
[Link](); // calls the lambda body
// Full form (multi-statement body):
Display d2 = () -> {
[Link]("Line 1");
[Link]("Line 2");
};
Security analogy: Regular class = bicycle outside (anyone can access). Inner class = bicycle inside
the house. Anonymous inner class = bicycle in the bedroom. Lambda = most concise and abstract.
Section 4 — Lambda Expression Deep Dive
Lambda Syntax Explained
Part Meaning
() Parameters of the abstract method (empty if no
params)
-> Separates parameters from body ('for this
method, the body is...')
{ body } Implementation of the abstract method
No method name Functional interface has ONE method — Java
knows which one
Why No Method Name in Lambda?
A functional interface has exactly ONE abstract method. Since there is only one method, Java
automatically knows which method the lambda body belongs to. There is no ambiguity — no need to
specify the name.
Comparison: Anonymous vs Lambda
Anonymous inner class Lambda expression
Display d = new Display() { Display d = () -> {
public void display() { [Link]("Hi");
[Link]("Hi"); };
}
};
Lambda with Parameters
@FunctionalInterface
interface Greet {
void greet(String name);
}
// Lambda with one parameter (parentheses optional for single param)
Greet g = name -> [Link]("Hello " + name);
[Link]("Alice"); // Output: Hello Alice
// Lambda with multiple parameters
// interface Add { int add(int a, int b); }
Add a = (x, y) -> x + y;
Lambda + Stream API (Advanced)
• Lambda expressions combine with Stream API to write powerful one-liners.
• Example: find 2nd largest, filter elements, sort — all in one line.
• This is a sought-after skill for developers with 2-3 years of experience.
// Find all even numbers from a list
[Link]().filter(n -> n % 2 == 0).collect([Link]());
// Sort strings by length
[Link]((a, b) -> [Link]() - [Link]());
Section 5 — Interview Questions & Answers
Q1. What is an interface? How has its definition changed over Java versions?
Before JDK 1.8: an interface is a collection of pure abstract methods. From JDK 1.8: an interface is a
collection of abstract methods and concrete methods (default, static, private, private static), used
primarily for standardization and to achieve multiple inheritance.
Q2. Why do we need interfaces when abstract classes already have abstract +
concrete methods?
Two key reasons: (1) Standardization — interfaces enforce a strict contract for all implementing
classes. (2) Multiple inheritance — a class can implement multiple interfaces but extend only one
abstract class. Real example: String implements Comparable, Serializable, and CharSequence
simultaneously.
Q3. What are JDK 8 features in interfaces?
Default methods and static methods. Default methods allow adding new features to an existing
interface without breaking existing implementing classes (backward compatibility). Static methods
provide interface-level utility methods that are not inherited by implementing classes.
Q4. What are JDK 9 features in interfaces?
Private methods and private static methods. These reduce code redundancy inside the interface.
Private methods are called by default methods; private static methods are called by static methods.
Neither type is accessible outside the interface.
Q5. What is backward compatibility? How do default methods achieve it?
Backward compatibility means adding new features without breaking existing functionality. When a
new method is added to an interface as a default method (with a body), all existing implementing
classes automatically inherit it — they do not need to be changed. This prevents compile errors
across hundreds of implementing classes.
Q6. Why can't you access a static interface method via an implementing class?
Static methods in interfaces are interface members, not class members. They are NOT inherited. You
must call them using the interface name: [Link](). Calling via [Link]() or
an object reference gives a compile error: 'The static method can only be accessed using the
interface type'.
Q7. What is a functional interface? Give real-world examples.
A functional interface has exactly one abstract method but can have any number of concrete
methods. Annotated with @FunctionalInterface. Examples: Runnable (run()), Comparable<T>
(compareTo() — used in String for lexicographic comparison), Comparator<T> (compare()). Key fact:
String class internally implements Comparable.
Q8. What are the 4 ways to implement a functional interface?
(1) Regular class — create a named class that implements the interface. (2) Inner class — a class
defined inside another class for better encapsulation. (3) Anonymous inner class — nameless class
defined and instantiated at the same location (syntax: new InterfaceName() { body }). (4) Lambda
expression — most concise: () -> body.
Q9. Why do we get 'decreasing visibility' error when implementing an interface
method without public?
Interface methods are implicitly public. In the implementing class, if you don't specify any access
modifier, it defaults to package-access, which is more restrictive than public. Java does not allow
reducing the visibility of an overridden method, so the compiler throws a 'Cannot reduce the visibility
of the inherited method' error.
Q10. Can you give a concrete method in an interface without default or static? Why or
why not?
No. An interface expects methods to be abstract by default. To provide a body you must use: default
(inherited by implementing classes), static (interface-only access), private (internal to interface), or
private static (internal static use). A plain instance method with a body causes a compile error.
Q11. What is an anonymous inner class and when is it used?
An anonymous inner class is a class without a name, defined and instantiated in one expression.
Syntax: InterfaceName ref = new InterfaceName() { override methods }; Used for one-time
implementations without creating a separate named class. More encapsulated than a regular class.
Most useful before lambda expressions were introduced (JDK 8).
Q12. How does a lambda expression relate to functional interfaces?
A lambda is shorthand for implementing a functional interface. Because there is exactly one abstract
method, Java knows which method the lambda body belongs to — no name needed. Syntax: () ->
body. The () holds parameters, -> separates them from the body. The most concise implementation.
The reference type must be the functional interface type.
Q13. What is the difference between default and static methods in interfaces?
Default methods ARE inherited by implementing classes and can be overridden. Static methods are
NOT inherited — they belong only to the interface and must be called via the interface name. Default
methods serve backward compatibility; static methods serve as interface-scoped utilities.
Q14. Why was private static method introduced in JDK 9?
A static method cannot call a non-static private method (static context restriction). When code needs
to be reused across multiple static interface methods, a private static helper is needed. Private static
methods reduce redundancy in static interface methods while keeping the helper inaccessible from
outside the interface.
Section 6 — Quick Reference Summary
Interface Evolution Timeline
Java Version What changed in interfaces
JDK 1.0 - 1.7 Only pure abstract methods allowed
JDK 1.8 (Java 8) Default methods + Static methods introduced
JDK 1.9 (Java 9) Private methods + Private static methods
introduced
All Method Types — Quick Reference
Method type JDK Has body? Inherited? Purpose
abstract Always No Yes (must Enforce contract
override)
default JDK 8 Yes Yes (optional Backward
override) compat.
static JDK 8 Yes No Interface utility
private JDK 9 Yes No Reduce
redundancy
private static JDK 9 Yes No Reduce
redundancy
Practice Task (from class)
Create an OperatingSystem interface with boot() and shutdown() abstract methods. Add
implementing classes: Windows, MacOS, Linux. Include ALL JDK 8 & 9 features: a default
updateOS() method, a static info() method, a private helper method, and a private static logAction()
method. Then implement the interface all 4 ways (regular class, inner class, anonymous inner class,
lambda).
End of Notes — Java Interfaces & JDK 8/9 Features