home

Interfaces

Overview

interface Foo {
    int foo();    // public abstract
    int FOO = 42; // public static final
}
class FooImpl implements Foo {
    @Override
    public int foo() {  // must be public!
        return Foo.FOO; // 42
    }
}

Static Methods in Interfaces

Calling a static method of a not-inherited interface

interface Bar {
    static void bar() {}
}
class Foo {
    void foo() {
        Bar.bar();
    }
}

Calling a static method of an inherited interface

interface Foo {
    static void foo() {}
}
class FooImpl implements Foo {
    void fooTest() {
        // This is not allowed:
        // foo();
        // Correct way is:
        Foo.foo();
    }
}

Inheritance in Static Methods in Interfaces

interface Foo {
    static void foo() {System.out.println("foo");}
}

interface Bar extends Foo {}

class App {
    public static void main(String[] args) {
        // This will not compile
        Bar.foo();
    }
}

Heads Up! Static methods are visible (though can not be overridden, can only be hidden) in class inheritance trees.

class Foo {
    static void foo() {System.out.println("foo");}
}

class Bar extends Foo {}

class App {
    public static void main(String[] args) {
        Bar.foo(); // foo
    }
}

Default Methods in Interfaces

interface Foo {
    default int foo() {
        return 42;
    }
}
class FooImpl implements Foo {
    // no need to override foo!
    void bar() {
        Foo f = new FooImpl();
        f.foo(); // 42
    }
}

Default Method Conflicts

interface Foo {
    default int foo() {
        return 42;
    }
}
interface Bar {
    default int foo() {
        return -42;
    }
}
class FooBar implements Foo, Bar {
    public int foo() {
        return 0;
    }
    // It would not make any difference if either Foo.foo or Bar.foo was abstract
}
class FooBar implements Foo, Bar {
    public int foo() {
        return Foo.super.foo(); // very weird syntax!
    }
}
interface Foo {
    default int foo() {
        return 42;
    }
}
class Bar {
    public int foo() {
        return -42;
    }
}
class FooBar extends Bar implements Foo  {
    void fooBar() {
        new FooBar().foo(); // -42
    }
}

Functional Interfaces

An interface with a single abstract method.

@FunctionalInterface
interface Foo {
    // single abstract method
    void foo();
    // equals method here is fine, it is inherited from the Object class 
    boolean equals(Object o);
}

class FooImpl implements Foo {
    @Override
    public void foo(){}
    // Implementing Foo does not mean equals method must be implemented
}

Functional Interfaces in JDK 8

Interface SAM1 Arguments Returns
Predicate test T boolean
BiPredicate test T, U boolean
Consumer accept T void
BiConsumer accept T, U void
Supplier get T
Function apply T R
UnaryOperator apply T T
BiFunction apply T, U R
BinaryOperator apply T, T T
1 Single Abstract Method

Primitive Specializations of Functional Interfaces in JDK 8

* Purely Primitive Interfaces are Printed in Bold

InterfaceSAMArgumentsReturns
Predicate
IntPredicatetestintboolean
LongPredicatetestlongboolean
DoublePredicatetestdoubleboolean
Consumer
IntConsumeracceptintvoid
LongConsumeracceptlongvoid
DoubleConsumeracceptdoublevoid
BiConsumer
ObjIntConsumeracceptT, intvoid
ObjLongConsumeracceptT, longvoid
ObjDoubleConsumeracceptT, doublevoid
Supplier
IntSuppliergetAsIntint
LongSuppliergetAsLonglong
DoubleSuppliergetAsDoubledouble
BooleanSuppliergetAsBooleanboolean
Function
IntFunctionapplyintR
LongFunctionapplylongR
DoubleFunctionapplydoubleR
ToIntFunctionapplyAsIntTint
ToLongFunctionapplyAsLongTlong
ToDoubleFunctionapplyAsDoubleTdouble
IntToDoubleFunctionapplyAsDoubleintdouble
IntToLongFunctionapplyAsLongintlong
LongToIntFunctionapplyAsIntlongint
LongToDoubleFunctionapplyAsDobulelongdouble
DoubleToIntFunctionapplyAsIntdoubleint
DoubleToLongFunctionapplyAsLongdoublelong
UnaryOperator
IntUnaryOperatorapplyAsIntintint
LongUnaryOperatorapplyAsLonglonglong
DoubleUnaryOperatorapplyAsDoubledoubledouble
BiFunction
ToIntBiFunctionapplyAsIntT, Uint
ToLongBiFunctionapplyAsLongT, Ulong
ToDoubleBiFunctionapplyAsDoubleT, Udouble
BinaryOperator
IntBinaryOperatorapplyAsIntint, intint
LongBinaryOperatorapplyAsLonglong, longlong
DoubleBinaryOperatorapplyAsDoubledouble, doubledouble

Examples

BiPredicate Example

import java.util.function.BiPredicate;

class FooBar {
    static class Foo {int foo = 42;}
    static class Bar {int bar = 42;}
    public static <T, U> boolean foo(T t, U u, BiPredicate<T,U> biPredicate) {
        return biPredicate.test(t, u);
    }
    public static void main(String[] args) {
        foo(new Foo(), new Bar(), (foo, bar) -> foo.foo == 42 && bar.bar == 42); // true
    }
}

References