1、小试牛刀
package org.chen.study;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SwingTest {
public static void main(String[] args) {
JFrame jFrame = new JFrame("this is title");
JButton jButton = new JButton("this is button");
// 为jButton添加事件
//在1.8之前我们的写法
// jButton.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// System.out.println("hello world");
// }
// });
//1.8引入lambda表达式
jButton.addActionListener(e -> {
System.out.println("hello world");
System.out.println("package");
});
jFrame.add(jButton);
jFrame.pack();
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
在lambda表达式中e的类型我们并没有定义,这里是根据java类型推断机制进行定义的,当然你也可以显示的显示e的类型
jButton.addActionListener((ActionListener) e -> {
System.out.println("hello world");
System.out.println("package");
});
2、函数式接口
package org.chen.study;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerTest {
public static void main(String[] args) {
List<Integer> ints = Arrays.asList(new Integer[]{2,2,23,4,5});
//for循环
for(int i = 0; i < ints.size(); i++){
System.out.println(ints.get(i));
}
System.out.println("-----------------");
//foreach循环
for (Integer integer : ints) {
System.out.println(integer);
}
System.out.println("-----------------");
//Consumer
ints.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(t);
}
});
System.out.println("------------------");
//利用lambda表达式简化consumer
ints.forEach(action -> System.out.println(action));
}
}
在上面的例子中,我么用到Consumer类,我们进入这个类中可以看见
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.util.function;
import java.util.Objects;
/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
可以看见Consumer是一个接口,而且这个接口加了一个注解@FunctionalInterface。这个注解声明这个接口是个函数式接口,
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
@FunctionalInterface源码
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.lang;
import java.lang.annotation.*;
/**
* An informative annotation type used to indicate that an interface
* type declaration is intended to be a <i>functional interface</i> as
* defined by the Java Language Specification.
*
* Conceptually, a functional interface has exactly one abstract
* method. Since {@linkplain java.lang.reflect.Method#isDefault()
* default methods} have an implementation, they are not abstract. If
* an interface declares an abstract method overriding one of the
* public methods of {@code java.lang.Object}, that also does
* <em>not</em> count toward the interface's abstract method count
* since any implementation of the interface will have an
* implementation from {@code java.lang.Object} or elsewhere.
*
* <p>Note that instances of functional interfaces can be created with
* lambda expressions, method references, or constructor references.
*
* <p>If a type is annotated with this annotation type, compilers are
* required to generate an error message unless:
*
* <ul>
* <li> The type is an interface type and not an annotation type, enum, or class.
* <li> The annotated type satisfies the requirements of a functional interface.
* </ul>
*
* <p>However, the compiler will treat any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
*
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
-------------------------------------------------------------------------
我们自定义一下函数式接口
package org.chen.study;
@FunctionalInterface
public interface MyFunctionalInterface {
}
这是编辑器提示错误了
提示说的很清楚 我们的接口不是一个函数式接口
我们至少可以得出一个结果:函数接口必须要有抽象方法。
这样我们就定义了一个函数接口
我们继续添加抽象方法
又出现错误信息了
我们可以大致推测出 函数式接口不能有两个抽象方法。
在看看下面的例子
我们添加了一个toString()方法,编辑器并没有报错
我们知道toString()方法是继承自Object对象的,那我们可以知道如果重写了java.lang.Object类的方法,那么这个方法不计入抽象方法数的。
再看看下面的例子
这里也是没有报错的。
这个是java8的新特性(接口中的默认方法),后面会说到。
在上面的源码注解中也说的很详细了。
在java中lambda表达式是对象,而不是函数;
我们看看下面的例子来体会一下:
package org.chen.study;
public class LambdaObject {
public static void main(String[] args) {
LambdaObject lambdaObject = new LambdaObject();
lambdaObject.test(() -> System.out.println("efg"));
}
public void test(MyFunctionalInterface myFunctionalInterface){
myFunctionalInterface.test();
}
}
这里我们运用了我们自定义的函数式接口MyFunctionalInterface。
我们上面说了lambda表达式在java中是对象,那就可以这么做
package org.chen.study;
public class LambdaObject {
public static void main(String[] args) {
// LambdaObject lambdaObject = new LambdaObject();
// lambdaObject.test(() -> System.out.println("efg"));
MyFunctionalInterface myFunctionalInterface = () -> {};
System.out.println(myFunctionalInterface.getClass());
System.out.println(myFunctionalInterface.getClass().getSuperclass());
System.out.println(myFunctionalInterface.getClass().getInterfaces()[0]);
}
public void test(MyFunctionalInterface myFunctionalInterface){
myFunctionalInterface.test();
}
}
在上面,我们将lambda表达式赋值给MyFunctionInterface对象。我们看到这个对象的一些信息。