Java Fundamentals

Interfaces in Java

Prepared By Krishna Srikanth M

1. Interfaces in Java

An interface in Java is a blueprint used for standardization and abstraction. It contains a contract that implementing classes must follow.

  • An interface is used for standardization.
  • It contains a skeleton that is implemented by a class.
  • An interface is a blueprint of a class.
  • It is used to achieve abstraction and support multiple inheritance through interfaces.
  • One class can implement multiple interfaces.
  • One interface can extend multiple interfaces.
  • Interface fields are public, static and final by default.
  • Traditional interface methods are public and abstract by default.
  • An interface is used by the implements keyword.
  • An interface cannot be instantiated directly and does not have constructors.

Why Use Java Interfaces?

  • To achieve abstraction.
  • To support multiple inheritance of type.
  • To achieve loose coupling.
  • To improve consistency and object-oriented design.
Compiler-added modifiers: Interface methods are implicitly public/abstract where applicable, while interface fields are implicitly public/static/final.
Interface overview and compiler-added modifiers from PDF page 1

2. Understanding the Relationship Between Classes and Interfaces

Java uses different keywords for relationships between classes and interfaces:

RelationshipKeyword
Class extends another classextends
Class implements an interfaceimplements
Interface extends another interfaceextends

A class can implement multiple interfaces, while an interface can extend multiple interfaces. This provides a way to model multiple inheritance of type in Java.

Class and interface relationships and multiple inheritance diagram from PDF page 2

3. Types of Interfaces in Java

The PDF identifies three main categories:

1. Normal Interface

The regular form of interface used to define method contracts.

2. Functional Interface

An interface with exactly one abstract method, suitable for lambda expressions and method references.

3. Marker Interface

An empty interface used to mark a class for special treatment by the runtime or frameworks.

Marker Interface

A marker or tagging interface contains no methods or fields. Its purpose is to associate metadata with a class and indicate that it has a particular property.

Examples: Serializable, Cloneable, Remote.

Interface types and marker interface explanation from PDF page 3

4. Normal Interface

A normal or regular interface is the standard form used to define method signatures and establish a contract for implementing classes.

Example: Printable

interface Printable {
    void print();
}

class A6 implements Printable {
    public void print() {
        System.out.println("Hello");
    }

    public static void main(String args[]) {
        A6 obj = new A6();
        obj.print();
    }
}

Example: Drawable

interface Drawable {
    void draw();
}

class Rectangle implements Drawable {
    public void draw() {
        System.out.println("drawing rectangle");
    }
}

class Circle implements Drawable {
    public void draw() {
        System.out.println("drawing circle");
    }
}

class TestInterface1 {
    public static void main(String args[]) {
        Drawable d = new Circle();
        d.draw();
    }
}
Loose coupling: Code can depend on the interface type instead of a specific implementation class.
Normal interface examples from PDF page 4

5. Multiple Inheritance in Java by Interface

If a class implements multiple interfaces, or an interface extends multiple interfaces, Java can model multiple inheritance of type.

Example: Bank Interface

interface Bank {
    float rateOfInterest();
}

class SBI implements Bank {
    public float rateOfInterest() {
        return 9.15f;
    }
}

class PNB implements Bank {
    public float rateOfInterest() {
        return 9.7f;
    }
}

class TestInterface2 {
    public static void main(String[] args) {
        Bank b = new SBI();
        System.out.println("ROI: " + b.rateOfInterest());
    }
}

Example: Implementing Multiple Interfaces

interface Printable {
    void print();
}

interface Showable {
    void show();
}

class A7 implements Printable, Showable {
    public void print() {
        System.out.println("Hello");
    }

    public void show() {
        System.out.println("Welcome");
    }

    public static void main(String args[]) {
        A7 obj = new A7();
        obj.print();
        obj.show();
    }
}
Multiple inheritance using interfaces examples from PDF page 5

6. Interface Inheritance

An interface can extend another interface. A class implementing the child interface must provide implementations for the abstract methods inherited from the parent interface.

interface Printable {
    void print();
}

interface Showable extends Printable {
    void show();
}

class TestInterface4 implements Showable {
    public void print() {
        System.out.println("Hello");
    }

    public void show() {
        System.out.println("Welcome");
    }

    public static void main(String args[]) {
        TestInterface4 obj = new TestInterface4();
        obj.print();
        obj.show();
    }
}

Default Methods

Modern Java interfaces can contain default methods with an implementation.

interface Drawable {
    void draw();

    default void msg() {
        System.out.println("default method");
    }
}

class Rectangle implements Drawable {
    public void draw() {
        System.out.println("drawing rectangle");
    }
}

class TestInterfaceDefault {
    public static void main(String args[]) {
        Drawable d = new Rectangle();
        d.draw();
        d.msg();
    }
}
Interface inheritance and default method examples from PDF page 6

7. Default Methods in Interfaces

A default method has a method body directly inside the interface. Implementing classes inherit the default implementation unless they override it.

Why default methods? They allow interfaces to evolve by adding new behavior without requiring every existing implementing class to immediately provide an implementation.

8. Static Methods in Interfaces

Interfaces can also contain static methods. Static interface methods belong to the interface itself and are called using the interface name.

Example

interface Drawable {
    void draw();

    static int cube(int x) {
        return x * x * x;
    }
}

class Rectangle implements Drawable {
    public void draw() {
        System.out.println("drawing rectangle");
    }
}

class TestInterfaceStatic {
    public static void main(String args[]) {
        Drawable d = new Rectangle();
        d.draw();

        System.out.println(Drawable.cube(3));
    }
}

Output

drawing rectangle
27
Static interface method and abstract class versus interface comparison from PDF page 7

Abstract Class vs Interface

Abstract ClassInterface
Can contain abstract and non-abstract methods.Can contain abstract methods plus default and static methods.
Does not support multiple inheritance of classes.Supports multiple inheritance of type through interfaces.
Can have final, non-final, static and non-static variables.Fields are public, static and final by default.
Can provide implementations and can implement interfaces.Defines a contract and can extend other interfaces.
Declared using the abstract keyword.Declared using the interface keyword.
Can extend a Java class and implement interfaces.Can extend other Java interfaces.
Subclass uses extends.Class uses implements.
Can have members with different access modifiers.Interface members are public by default where applicable.

9. Functional Interface / SAM Interface

A functional interface has exactly one abstract method. It is also called a SAM (Single Abstract Method) interface.

  • It has exactly one abstract method.
  • It can have multiple default or static methods.
  • It can be implemented using lambda expressions and method references.
  • The @FunctionalInterface annotation is optional but recommended.
  • The annotation causes a compiler error if the interface contains more than one abstract method.

Example

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

Examples of Functional Interfaces

  • Runnable — contains run()
  • Comparable — contains compareTo()
  • ActionListener — contains actionPerformed()
  • Callable — contains call()
Functional interface and SAM interface diagram from PDF page 8

10. Functional Interface Lambda Examples

Predicate

public class PredicateExample {
    public static void main(String[] args) {
        Predicate<String> isLongerThan5 = s -> s.length() > 5;

        System.out.println(isLongerThan5.test("Hello"));      // false
        System.out.println(isLongerThan5.test("Functional")); // true
    }
}

BiPredicate

public class BiPredicateExample {
    public static void main(String[] args) {
        BiPredicate<String, Integer> isLengthEqual =
            (str, len) -> str.length() == len;

        System.out.println(isLengthEqual.test("Java", 4));   // true
        System.out.println(isLengthEqual.test("Spring", 3)); // false
    }
}

Function

public class FunctionExample {
    public static void main(String[] args) {
        Function<String, Integer> stringLength = s -> s.length();

        System.out.println(stringLength.apply("Java"));       // 4
        System.out.println(stringLength.apply("Function"));   // 8
    }
}
Predicate BiPredicate and Function lambda examples from PDF page 9

BiFunction

public class BiFunctionExample {
    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> add =
            (a, b) -> a + b;

        System.out.println(add.apply(10, 20)); // Output: 30
        System.out.println(add.apply(5, 3));   // Output: 8
    }
}

Consumer

public class ConsumerExample {
    public static void main(String[] args) {
        Consumer<String> greeter =
            name -> System.out.println("Hello, " + name);

        greeter.accept("Alice"); // Hello, Alice
        greeter.accept("Bob");   // Hello, Bob
    }
}

BiConsumer

public class BiConsumerExample {
    public static void main(String[] args) {
        BiConsumer<String, Integer> printInfo =
            (name, age) ->
                System.out.println(name + " is " + age + " years old.");

        printInfo.accept("Alice", 25);
        printInfo.accept("Bob", 30);
    }
}
BiFunction Consumer and BiConsumer examples from PDF page 10

BiConsumer with Map

Map<String, Integer> marks = new HashMap<>();
marks.put("Math", 90);
marks.put("Science", 85);
marks.put("English", 92);

BiConsumer<String, Integer> displayEntry =
    (subject, score) ->
        System.out.println(subject + " = " + score);

marks.forEach(displayEntry);

BiConsumer andThen()

BiConsumer<String, Integer> print =
    (name, age) ->
        System.out.println("Name: " + name + ", Age: " + age);

BiConsumer<String, Integer> greet =
    (name, age) ->
        System.out.println("Hello " + name +
                           "! You are " + age +
                           " years young.");

BiConsumer<String, Integer> combined =
    print.andThen(greet);

combined.accept("Alice", 25);

Supplier

Supplier<Integer> randomSupplier =
    () -> new Random().nextInt(100);

System.out.println(randomSupplier.get());
System.out.println(randomSupplier.get());
BiConsumer Supplier andThen examples from PDF page 11

11. Java Built-in Functional Interfaces

InterfacePurposeTypical Method
Function<T,R>Accepts one value and returns a result.apply()
BiFunction<T,U,R>Accepts two values and returns a result.apply()
Consumer<T>Accepts one value and performs an action.accept()
BiConsumer<T,U>Accepts two values and performs an action.accept()
Supplier<T>Supplies a value without taking an input.get()
Predicate<T>Tests one value and returns boolean.test()
BiPredicate<T,U>Tests two values and returns boolean.test()
UnaryOperator<T>Accepts and returns the same type.apply()
BinaryOperator<T>Combines two values of the same type.apply()

UnaryOperator

public class UnaryOperatorExample {
    public static void main(String[] args) {
        UnaryOperator<String> toUpperCase =
            str -> str.toUpperCase();

        System.out.println(toUpperCase.apply("java"));     // JAVA
        System.out.println(toUpperCase.apply("function")); // FUNCTION
    }
}

BinaryOperator

public class BinaryOperatorExample {
    public static void main(String[] args) {
        BinaryOperator<Integer> add = (a, b) -> a + b;

        System.out.println(add.apply(10, 20)); // Output: 30
    }
}

Stream reduce with BinaryOperator

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

BinaryOperator<Integer> sum = (a, b) -> a + b;

int result = numbers.stream().reduce(0, sum);

System.out.println("Sum: " + result); // Output: Sum: 15
UnaryOperator BinaryOperator and stream reduce examples from PDF page 12

12. Key Characteristics & Quick Revision

Static Methods in Interfaces

  • Static methods belong to the interface itself, not to implementing objects.
  • They are not inherited by implementing classes.
  • They cannot be overridden.
  • They are called directly using the interface name.

Default Methods in Interfaces

  • Default methods contain an implementation inside the interface.
  • They are inherited by implementing classes.
  • An implementing class can override them.
  • They allow interfaces to evolve without breaking existing implementations.

Quick Revision

ConceptKey Point
InterfaceDefines a contract/blueprint for implementing classes.
implementsUsed by a class to implement an interface.
extendsUsed by an interface to extend another interface.
Multiple inheritanceA class can implement multiple interfaces.
Normal interfaceRegular interface containing method contracts plus supported default/static members.
Functional interfaceExactly one abstract method; works naturally with lambdas.
Marker interfaceEmpty interface used as a tag or marker.
Default methodInterface method with a body; can be inherited and overridden.
Static interface methodBelongs to the interface and is called using the interface name.
Core idea: Interfaces provide abstraction, standardization, loose coupling and a way to model multiple inheritance of type. Functional interfaces additionally provide a natural target for lambda expressions.
Static and default interface method characteristics from PDF page 13