Skip to content

Single Abstract Method (SAM)

Hu JiaJun edited this page Nov 29, 2020 · 1 revision

@FunctionalInterface

This annotation can be used for the definition of an interface. Once the annotation is used to define the interface, the compiler will force to check whether the interface has one and only abstract method, otherwise an error will be reported. But this annotation is not necessary, as long as it conforms to the definition of a functional interface, then this interface is a functional interface.

/**
 * When a method with SAM as a parameter is called, a Lambda expression can be used as this parameter.
 * According to the principle of SAM, in this interface, only one method needs to be implemented,
 * but there are exceptions as below:
 *     1. default methods and static methods do not affect the contract of the 
 *        functional interface, feel free to use them.
 *     2. Object public methods can be overrided, such as equals, toString, hashcode, etc. 
 *        clone method is protected, so it cannot be overrided.
 */

@FunctionalInterface
public interface IFITest {

    void test(String s);

    // The class that implements the interface and sub-interface will not 
    // inherit the static methods in the interface
    // this is a static method
    static void test1() {
        System.out.println("test1");
    }

    // this is a default method
    default void test2() {
        System.out.println("test2");
    }

    @Override
    String toString();

    @Override
    boolean equals(Object object);

    @Override
    int hashCode();
}

Implement:

public class FITest {
    public static void main(String[] args) {
        String text = "Hello World";
        printString(text, System.out::print);
    }

    private static void printString(String text, IFITest iFITest) {
        iFITest.test(text);
    }
}

/* Output */
Hello World

Inheritance of functional interfaces

@FunctionalInterface
public interface IFITest2 {

    // Must be the same as the abstract method of IFITest
    void test(String s);
}

@FunctionalInterface
public interface IFITest3 extends IFITest, IFITest2 {

    // Must be the same as the abstract method of IFITest and IFITest2
    void test(String s);
}

Implement:

public class FITest {
    public static void main(String[] args) {
        String text = "Hello World";
        printString(text, System.out::print);
    }

    private static void printString(String text, IFITest3 iFITest3) {
        iFITest3.test(text);
    }
}

/* Output */
Hello World
Clone this wiki locally