1、匿名内部类:
在java8之前,我们经常对runnable、swing之类的使用匿名内部类,例如
JButton testButton = new JButton("Test Button");
        testButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ae)
            {
                System.out.println("Click Detected by Anon Class");
            }
        });我们先来看下ActionListener接口的定义:
package java.awt.event;
import java.util.EventListener;
public interface ActionListener extends EventListener {
    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);
}我们发现这个接口中只有一个方法。对于上面那种匿名内部类的写法,主要是为了优雅,否则你需要针对每一个事件写一个单独的ActionListener接口的实现类(仅仅为了定义一个方法就需要附加写一大堆的代码)。通常,哪里需要,就在哪里创建对应的匿名内部类,这样的代码可读性会更强。
在java8中,我们对上面这种只有一个抽象方法接口叫做函数式接口。通常在Java中,我们经常使用匿名内部类来实现函数式接口,这是一种很常见的使用模式;
2、函数式接口:
1)用途:
它们主要用在Lambda表达式和方法引用(实际上也可认为是Lambda表达式)上。
@FunctionalInterface
interface GreetingService {
        void sayMessage(String message);
}那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):
GreetingService greetService1 = message -> System.out.println("Hello " + message);2)关于@FunctionalInterface注解:
Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。正确例子,没有报错:
@FunctionalInterface
    interface GreetingService
    {
        void sayMessage(String message);
    }错误例子,接口中包含了两个抽象方法,违反了函数式接口的定义,Eclipse报错提示其不是函数式接口。

注:加不加@FunctionalInterface对于接口是不是函数式接口没有影响,该注解知识提醒编译器去检查该接口是否仅包含一个抽象方法
3)函数式接口里允许定义默认方法:
函数式接口里是可以包含默认方法,因为默认方法不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的;如下代码不会报错:
@FunctionalInterface
interface GreetingService{
  void sayMessage(String message);
  default void doSomeMoreWork1(){
    // Method body
  }
  default void doSomeMoreWork2(){
    // Method body
  }
}4)函数式接口里允许定义静态方法:
函数式接口里是可以包含静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义的;
@FunctionalInterface
interface GreetingService {
  void sayMessage(String message);
  static void printHello(){
    System.out.println("Hello");
  }
}5)函数式接口里允许定义java.lang.Object里的public方法:
函数式接口里是可以包含Object里的public方法,这些方法对于函数式接口来说,不被当成是抽象方法(虽然它们是抽象方法);因为任何一个函数式接口的实现,默认都继承了Object类,包含了来自java.lang.Object里对这些抽象方法的实现;
@FunctionalInterface
interface GreetingService  {
  void sayMessage(String message);
  
  @Override
  boolean equals(Object obj);
}JDK中的函数式接口举例
java.lang.Runnable,
java.awt.event.ActionListener, 
java.util.Comparator,
java.util.concurrent.Callable
java.util.function包下的接口,如Consumer、Predicate、Supplier等
                









