[Java] Functional interface of new features of JDK8

Insert picture description here

Original: http://www.javastack.cn/article/2017/jdk8-new-feature-functional-interface/

What is a functional interface

Let's first take a look at how the traditional thread creation is written

Thread t1 = new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("t1");
	}
});
t1.start();

Let's take a look at how to write a functional interface

Thread t2 = new Thread(() -> System.out.println("t2"));
t2.start();

The Runnable interface can be directly written using Lambda expressions. This is because the Runnable interface is a functional interface. Let's take a look at the source code of Runnable.

@FunctionalInterface
public interface Runnable {

    public abstract void run();
    
}

It is found that the interface has been added with a functional interface definition annotation: @FunctionalInterface, indicating that the interface is a functional interface.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {
    
}

In JDK8, in addition to the Runnbale interface, there are also interfaces such as Comparator, Callable, etc., which are defined as functional interfaces with this annotation.

Built-in functional interface
JDK8 provides several built-in functional interfaces, which can be used in many API places and can satisfy most applications.

//Consumer<T> - T作为输入,执行某种动作但没有返回值
Consumer<String> con = (x) -> {
	System.out.println(x);
};
con.accept("hello world");

//Supplier<T> - 没有任何输入,返回T
Supplier<String> supp = () -> {
	return "Supplier";
};
System.out.println(supp.get());

//Predicate<T> -T作为输入,返回的boolean值作为输出
Predicate<String> pre = (x) -> {
	System.out.print(x);
	return x.startsWith("op");
};
System.out.println(": " + pre.test("op, hello World"));

// Function<T, R> -T作为输入,返回的R作为输出
Function<String, String> function = (x) -> {
	System.out.print(x + ": ");
	return "Function";
};
System.out.println(function.apply("hello world"));

//BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
BinaryOperator<String> bina = (x, y) -> {
	System.out.print(x + " " + y);
	return "BinaryOperator";
};
System.out.println("  " + bina.apply("hello ", "world"));

Custom functional interface

1. Customize a functional interface

@FunctionalInterface
public interface CalcInterface<N, V> {	
	V operation(N n1, N n2);
}

There is only one abstract method here. The @FunctionalInterface annotation does not need to be written. As for why you can look down.

2. Create a new class that references a functional interface

public static class NumberOperation<N extends Number, V extends Number> {

	private N n1;
	private N n2;

	public NumberOperation(N n1, N n2) {
		this.n1 = n1;
		this.n2 = n2;
	}

	public V calc(CalcInterface<N, V> ci) {
		V v = ci.operation(n1, n2);
		return v;
	}

}

3. Test the functional interface

private static void testOperationFnInterface() {
        NumberOperation<Integer, Integer> np = new NumberOperation(13, 10);
    
	CalcInterface<Integer, Integer> addOper1 = (n1, n2) -> {
		return n1 + n2;
	};
	CalcInterface<Integer, Integer> multiOper1 = (n1, n2) -> {
		return n1 * n2;
	};
	System.out.println(np.calc1(addOper1));
	System.out.println(np.calc1(multiOper1));
	
	// 上面的可以简写为
	System.out.println(np.calc1((n1, n2) -> n1 + n2));
	System.out.println(np.calc1((n1, n2) -> n1 * n2));
}

The final output:

23
130
23
130

Functional interface specification

1. @FunctionalInterface indicates that a functional interface can only be used on an interface with only one abstract method.

2. Static methods, default methods, and methods overriding the Object class in the interface are not considered abstract methods.

3. The @FunctionalInterface annotation is not necessary. If the interface has only one abstract method, it is not necessary to write it. It conforms to the functional interface by default, but it is recommended to write this annotation. The compiler will check whether the interface conforms to the functional interface specification.

Give examples to illustrate the
correct functional interface.

@FunctionalInterface
public interface CalcInterface<N, V> {	
	V operation(N n1, N n2);
}

It's okay to add a few methods that conform to the functional style, and the compiler will not report an error.

@FunctionalInterface
public interface CalcInterface<N, V> {		

	V operation(N n1, N n2);
   
	public boolean equals(Object object);

	public default void defaultMethod() {

	}

	public static void staticMethod() {

	}
}

This useless @FunctionalInterface functional interface has two abstract methods that cannot be used in Lambda expressions.

public interface CalcInterface<N, V> {	
	V operation(N n1, N n2);
	V operation2(N n1, N n2);
}

The functional interface annotated with @FunctionalInterface with two abstract methods will report an error when compiled.

@FunctionalInterface
public interface CalcInterface<N, V> {	
	V operation(N n1, N n2);
	V operation2(N n1, N n2);
}

There is no abstract method for this, and compilation errors are reported.

public interface CalcInterface<N, V> {	
}

Guess you like

Origin blog.csdn.net/qq_21383435/article/details/108492967