Default, Static and Private Methods in Interfaces

Naveen AnamaneniUpdated · 6 min read

Suppose PaymentMethod is used by fifty classes, and now every payment needs a receipt(). Before Java 8, adding a method to an interface broke every class that implemented it. Default methods solved that: an interface method can now carry a body that implementing classes inherit, and override only if they want to. Java 8 also allowed static methods in interfaces, and Java 9 added private methods so that defaults can share helper code.

Four Kinds of Interface Method

Abstract, default, static and private methods
Receipts.java▶ Try it
public class Receipts {
    interface PaymentMethod {
        String name();
        long fee(long amount);
 
        default String receipt(String customer, long amount) {
            return customer + " paid " + rupees(amount + fee(amount))
                + " by " + name() + feeNote(amount);
        }
 
        private String feeNote(long amount) {
            long f = fee(amount);
            return f == 0 ? "" : " (fee " + rupees(f) + ")";
        }
 
        static String rupees(long amount) { return "Rs. " + amount; }
    }
 
    static class Upi implements PaymentMethod {
        public String name() { return "UPI"; }
        public long fee(long amount) { return 0; }
    }
 
    static class Card implements PaymentMethod {
        public String name() { return "card"; }
        public long fee(long amount) { return amount * 2 / 100; }
    }
 
    static class NetBanking implements PaymentMethod {
        public String name() { return "net banking"; }
        public long fee(long amount) { return 10; }
 
        @Override
        public String receipt(String customer, long amount) {
            String usual = PaymentMethod.super.receipt(customer, amount);
            return "Bank ref 7731. " + usual;
        }
    }
 
    public static void main(String[] args) {
        System.out.println(new Upi().receipt("Navika", 1500));
        System.out.println(new Card().receipt("Srihitha", 1500));
        System.out.println(new NetBanking().receipt("Advitha", 1500));
        System.out.println(PaymentMethod.rupees(99));
    }
}
Output
Navika paid Rs. 1500 by UPI
Srihitha paid Rs. 1530 by card (fee Rs. 30)
Bank ref 7731. Advitha paid Rs. 1510 by net banking (fee Rs. 10)
Rs. 99

How it works

  1. name() and fee() are abstract: every class must implement them.
  2. default String receipt(...) has a body. Upi and Card inherit it unchanged. Inside, it calls the abstract methods, so each class's own fee and name are used.
  3. NetBanking overrides the default and reuses it with PaymentMethod.super.receipt(...), the syntax for calling an interface's default version.
  4. private String feeNote is a helper shared by default methods. Implementing classes can't see or call it.
  5. static String rupees belongs to the interface and is called as PaymentMethod.rupees(99).

Try it yourself: add a Wallet class with a fee of Rs. 5, and print a receipt for Navika's Rs. 250 order.

The Rules

KindBody?Inherited by classes?Call it asSince
AbstractNoMust be implementedobj.name()Java 1.0
defaultYesYes, can be overriddenobj.receipt(...)Java 8
staticYesNoPaymentMethod.rupees(99)Java 8
privateYesNo, invisible outsideOnly from the interface's own methodsJava 9
private staticYesNoFrom the interface's static or default methodsJava 9

Static interface methods aren't inherited, even by implementing classes. Upi.rupees(99) fails with cannot find symbol. This avoids ambiguity when a class implements two interfaces with the same static method.

Defaults Can't Override Object Methods

E4.java
interface Greeter {
    default String toString() { return "Greeter"; }
}
Compiler output
E4.java:2: error: default method toString in interface Greeter overrides a member of java.lang.Object
    default String toString() { return "Greeter"; }
                   ^
1 error

Every class already inherits toString, equals and hashCode from Object, and class methods always win over interface defaults. A default version could never run, so Java forbids it.

Defaults in the JDK

Java 8 used defaults to add features to old interfaces without breaking millions of classes:

InterfaceDefault method added
IterableforEach(action)
Collectionstream(), removeIf(filter)
Listsort(comparator), replaceAll(op)
MapgetOrDefault, putIfAbsent, merge
Comparatorreversed(), thenComparing(...)

Common Mistakes

Calling a static interface method through a class or object. Use the interface name.

Using super.receipt() in the class. For interface defaults, write InterfaceName.super.receipt().

Trying to keep state in a default method. Interfaces have no instance fields; defaults can only use the abstract methods and parameters.

Interview Corner

Why were default methods added to interfaces in Java 8?

To let interfaces evolve without breaking existing implementations. Adding an abstract method forces every implementing class to change, but a default method provides a body that classes inherit automatically. Java 8 used this to add methods such as forEach, stream and sort to collection interfaces.

What is the difference between default and static methods in an interface?

Default methods are instance methods with a body; implementing classes inherit them and can override them, and they're called on an object. Static methods belong to the interface itself, aren't inherited by implementing classes or subinterfaces, can't be overridden, and are called as InterfaceName.method().

Why does Java 9 allow private methods in interfaces?

So default and static methods can share helper code without exposing it. Before Java 9, a shared helper had to be a public default or static method, which became part of the interface's public contract.

Practice

  1. Easy: Add a default method boolean isFree(long amount) to PaymentMethod that returns true when the fee is zero. Call it on each class.
  2. Harder: Add static PaymentMethod of(String code) that returns a Upi, Card or NetBanking object for the codes "UPI", "CARD" and "NB", and use it in main.

Quick check: Default, static and private methods

4 questions
1Which interface methods do implementing classes inherit?
2How does an overriding method call an interface's default version?
3How do you call a static method rupees declared in PaymentMethod?
4Can an interface declare default String toString()?

Key Takeaways

Was this tutorial helpful?

Lesson 136 of 482