转载 JDK8 新特性 函数式接口、接口默认方法

分类:2017-07-21 15:58:03   318人阅读  评论   分享
一. 函数式接口
        如果一个接口定义唯一一个抽象方法,那么这个接口就可以成为函数式接口,如 Runnable,Callable 接口。
        可以在函数式接口前加一个 @FunctionalInterface注解,非必须。在接口中添加了@FunctionalInterface,只允许有一个抽象方法,否则编译器也报错。Java8 中 Runnable 接口就是一个函数式接口,如下:
  1. @FunctionalInterface  
  2. public interface Runnable {  
  3.     /** 
  4.      * When an object implementing interface <code>Runnable</code> is used 
  5.      * to create a thread, starting the thread causes the object's 
  6.      * <code>run</code> method to be called in that separately executing 
  7.      * thread. 
  8.      * <p> 
  9.      * The general contract of the method <code>run</code> is that it may 
  10.      * take any action whatsoever. 
  11.      * 
  12.      * @see     java.lang.Thread#run() 
  13.      */  
  14.     public abstract void run();  
  15. }  

        像Runnable,Callable等有且只有一个抽象方法的接口,一般称为单一抽象方法接口,我们平常使用它的时候,比较习惯于使用一个内部类,这至少也要几行的代码,如下:
  1. public class AnonymousInnerClassTest {  
  2.   public static void main(String[] args) {  
  3.     new Thread(new Runnable() {  
  4.       @Override  
  5.       public void run() {  
  6.         System.out.println("A thread created and running ...");  
  7.       }  
  8.     }).start();  
  9.   }  
  10. }  

        如果我们声明为函数式接口,再结合Lambda表达式,那么一行代码就可以搞定,比较方便。如下代码:
  1. /* 
  2. * Implementing the interface by creating an 
  3. * anonymous inner class versus using  
  4. * lambda expression. 
  5. */  
  6. public class SimpleFunInterfaceTest {  
  7.   public static void main(String[] args) {  
  8.     carryOutWork(new SimpleFuncInterface() {  
  9.       @Override  
  10.       public void doWork() {  
  11.         System.out.println("Do work in SimpleFun impl...");  
  12.       }  
  13.     });  
  14.   
  15.     carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));  
  16.   }  
  17.   public static void carryOutWork(SimpleFuncInterface sfi){  
  18.     sfi.doWork();  
  19.   }  
  20. }  

输出为:
  1. Do work in SimpleFun impl...  
  2. Do work in lambda exp impl...  

        当然,一个接口也可以继承另外一个函数式接口,只要它不再声明抽象方法(可以使用默认方法),那么它也是一个函数式接口。
例如:
  1. @FunctionalInterface  
  2. public interface ComplexFunctionalInterface extends SimpleFuncInterface {  
  3.   default public void doSomeWork(){  
  4.     System.out.println("Doing some work in interface impl...");  
  5.   }  
  6.   default public void doSomeOtherWork(){  
  7.     System.out.println("Doing some other work in interface impl...");  
  8.   }  
  9. }  


总结:好处在哪里?

         结合Lambda表达式,比之前更加的简便。

二. 接口默认方法
        Java8 可以在 interface 中有方法的实现,也称为默认方法。那么 interface 中 有了方法的实现,也就是说,可以实现多继承,(当然之前利用一些方法也可以实现多继承,但是Java 一直不提倡多继承)。
        那么为什么现在加入了默认方法实现多继承呢?因为 interface 太过依赖他们的实现类了,要往 interface中加入一个方法就必须修改所有的实现类。那么Java8 中加入一些特性可能需要修改一些核心类,但是很多核心类不仅仅JDK中实现,很多第三方库中也会有实现,那么一改动可能就会出现兼容性问题。那么默认方法就可以很好的处理这个问题。
        代码示例:
  1. interface ITest {  
  2.     public default void sayHello(){  
  3.         System.out.println("Hello");  
  4.     }  
  5. }  
  6. public class Test implements ITest{  
  7.     public static void main(String[] args) {  
  8.         new Test().sayHello();  
  9.     }  
  10. }  

注意,需要加一个 default。


参考:


分享到: