这次在写实验六的时候解除了一个新的东西,java lambda表达式,它是java 8 新加入的。它使得java的代码更加精炼紧凑。
Java lambda表达式通常用于实现简单的事件侦听器(event listeners)/回调(callbacks),或者使用Java
Streams API进行函数式编程。
实现事件侦听器:
在java7中,如果你需要区实现一个方法去为某个状态变化侦听的化,想像你拥有一个类叫做stateowner,你需要添加一个匿名接口的实现:
StateOwner
stateOwner = new StateOwner();
stateOwner.addStateListener(new StateChangeListener() {
public void onStateChange(State oldState, State newState) {
// do something with the old and new
state.
}
});
首先在这个过程中,stateowner的实例被建立,然后实现StateChangeListener接口匿名类的实现又被当作一个侦听器加入到stateowner的实例中,
但是你在java8中就可以这么做:
StateOwner
stateOwner = new StateOwner();
stateOwner.addStateListener(
(oldState, newState) -> System.out.println("State changed")
);
Lambda表达式匹配了一个addStateListener()的参数类型,如果lambda表达式匹配了参数类型,lamda表达式就会被转换成为一个和参数一样可以实现同样接口的函数
Java的lambda表达式仅仅可以被用作匹配只有一个方法的接口。
但是以下的情况也是可以用lamda表达式的:
import java.io.IOException;
import java.io.OutputStream;
public interface MyInterface {
void printIt(String text);
default public void printUtf8To(String text, OutputStream outputStream){
try {
outputStream.write(text.getBytes("UTF-8"));
} catch (IOException e) {
throw new RuntimeException("Error writing String as UTF-8 to OutputStream", e);
}
}
static void printItToSystemOut(String text){
System.out.println(text);
}
}
上述代码我们可以看得到,
PrintIt方法并没有被实现
PrintUtf8To已经被实现了
printItToSystemOut也已经实现了
因而这种情况就可以使用lamda表达式:
MyInterface myInterface = (String text) -> {
System.out.print(text);
};
即使lambda表达式很接近于匿名接口实现,但是仍然有一些不同值得注意:
主要一点是状态:
匿名接口实现可以拥有状态
Lambda表达式不能拥有状态;
例如以下这个例子:
public interface MyEventConsumer {
public void consume(Object event);
}
匿名MyEventConsumer实现可以拥有它的自己的内部状态:
MyEventConsumer myEventConsumer = new MyEventConsumer() {
private int eventCount = 0;
public void consume(Object event) {
System.out.println(event.toString() + " consumed " + this.eventCount++ + " times.");
}
};
我们不难发现它拥有一个叫做eventCount的字段,这是Lambda做不到的。
Lambda参数:
因为java lamda
表达式和方法一样有效,那么他的参数也同样如此。
public void onStateChange(State oldState, State newState);
中,oldstate与newstate即为其返回。也存在无参数的情况,你可把你的lambda写做如下,当然也存在单参,多参的情况:
() -> System.out.println("Zero parameter lambda");
param -> System.out.println("One parameter: " + param);
(p1, p2) -> System.out.println("Multiple parameters: " + p1 + ", " + p2);
如果编译器无法从lambda匹配的功能接口方法推断出参数类型,则有时可能需要为lambda表达式指定参数类型。编译器会告诉你何时是这种情况。 这是一个Java lambda参数类型示例:
(Car car) -> System.out.println("The car is: " + car.getName());
如同你看的,类型Car是在car 参数之前写的,就像你可能在方法中定义一个参数一样,或者当完成接口的一个匿名类的时候。
从lambda表达式返回值:
你可以从lambda的表达式返回值,就像你可以从一个方法那得到返回值一样,你可以给lambda函数体增加一个返回值:
(param) -> {
System.out.println("param: " + param);
return "return value";
}
你也可以这样编写:
(a1, a2) -> { return a1 > a2; }
或者写
(a1, a2) -> a1 > a2;
编译器会明白a1>a2是lambda表达式的返回值。
Lambda也同样也是一个重要的对象。你可以将一个lambda表达式赋值给一个变量或者将他传递,就像对任何对象所作的那样,例如:
public interface MyComparator {
public boolean compare(int a1, int a2);
}
MyComparator myComparator = (a1, a2) -> return a1 > a2;
boolean result = myComparator.compare(2, 5);
第一个代码块显示了lambda表达式实现的接口。
第二个代码块显示了lambda表达式的定义,lambda表达式如何赋给变量,以及最后如何通过调用它实现的接口方法来调用lambda表达式。
以上例子以及学习内容详细可看:(出处)