java8的新特性

  1. 接口默认方法(Default Methods)
  2. 函数式接口(SAM类型的接口(Single Abstract Method))
  3. lambda表达式 
  4. 方法引用

 

接口默认方法(Default Methods)

 

接口定义:

public interface FunctionInter {

    /**
     *  接口默认方法1 (默认方法可有多个)
     */
    default String testdefaultFunction1(){
        System.out.println("testdefaultFunction1");
        return "testdefaultFunction1";
    }

    /**
     *  接口默认方法2 (默认方法可有多个)
     * @return
     */
    default String testdefaultFunction2(){
        System.out.println("testdefaultFunction2");
        return "testdefaultFunction2";
    }

    /**
     * 接口可定义静态变量
     */
    public static String foo = "foo";

    /**
     * 接口可定义静态方法
     * @return
     */
    public static String testFunctionInterStatic(){
        System.out.println("testFunctionInter");
        return "testFunctionInterStatic";
    }

    /**
     * 接口可定义抽象方法
     */
    public abstract void testAbstract();

}

 接口实现:

public class FunctionInterfaceTest implements FunctionInter {

    @Override
    public void testAbstract() {
        System.out.println("testAbstract");
    }

    public static void main(String[] args) {

        FunctionInterfaceTest item = new FunctionInterfaceTest();

        //默认方法
        item.testdefaultFunction1();
        //默认方法
        item.testdefaultFunction2();
        //抽象方法
        item.testAbstract();
        //接口静态方法调用 通过接口来调用
        FunctionInter.testFunctionInterStatic();// 接口静态方法调用 正确

        // item.testFunctionInterStatic(); 接口静态方法调用 错误

        // FunctionInterfaceTest.testFunctionInterStatic(); 接口静态方法调用 错误

        //接口静态变量调用 通过实现类来调用
        System.out.println(FunctionInterfaceTest.foo);
        //接口静态变量调用 通过接口来调用
        System.out.println(FunctionInter.foo);
    }
}

 

  • 接口定义中新增带有默认实现的方法
  • 接口定义抽象方法
  • 接口定义静态变量和静态实现方法
  • 静态变量可被实现类引用,静态实现方法不可以被实现类引用

 

函数式接口

 

函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract Method)。定义了这种类型的接口,使得以其为参数的方法,可以在调用时,使用一个lambda表达式作为参数。从另一个方面说,一旦我们调用某方法,可以传入lambda表达式作为参数,则这个方法的参数类型,必定是一个函数式的接口,这个类型会使用@FunctionalInterface进行修饰,或者抽象方法只有一个的接口不用@FunctionalInterface修饰也可作为函数式接口来用。

 

从SAM原则上讲,这个接口中,只能有一个函数需要被实现,但是也可以有如下例外:

             1. 默认方法与静态方法并不影响函数式接口的契约,可以任意使用,即

 

     函数式接口中可以有静态方法,一个或者多个静态方法不会影响SAM接口成为函数式接口,并且静态方法可以提供方法实现

 

     可以由 default 修饰的默认方法方法,这个关键字是Java8中新增的,为的目的就是使得某一些接口,原则上只有一个方法被实现,但是由于历史原因,不得不加入一些方法来兼容整个JDK中的API,所以就需要使用default关键字来定义这样的方法

 

    2. 可以有 Object 中覆盖的方法,也就是 equals,toString,hashcode等方法。

 

JDK中以前所有的函数式接口都已经使用 @FunctionalInterface 定义,可以通过查看JDK源码来确认,以下附JDK 8之前已有的函数式接口:

 

            java.lang.Runnable

 

            java.util.concurrent.Callable

 

            java.security.PrivilegedAction

 

            java.util.Comparator

 

            java.io.FileFilter

 

            java.nio.file.PathMatcher 

 

            java.lang.reflect.InvocationHandler

 

            java.beans.PropertyChangeListener

 

            java.awt.event.ActionListener  

 

            javax.swing.event.ChangeListener

 

 

函数式接口定义方式1 (不用@FunctionalInterface修饰,但是函数式接口必须只有一个抽象待实现的方法,可以包含其他的默认的实现方法或者静态的已实现方法)

public interface FunctionInterfaceDefine {

    public String functionBody();

    default  String defaultBody(){
        return "defaultBody";
    }

}
 
函数式接口定义方式2 ( 函数式接口必须只有一个抽象待实现的方法,可以包含其他的默认的实现方法或者静态的已实现方法
@FunctionalInterface 
public interface FunctionInterfaceDefineByAnnotation {

    public String functionBody();

    default  String defaultBody(){
        return "defaultBody";
    }

}
 

 

 

lambda表达式 

一个不用被绑定到一个标识符上,并且可能被调用的函数。这个解释还不够通俗,lambda表达式可以这样定义(不精确,自己的理解):一段带有输入参数的可执行语句块

 语法

 

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {

  statment1;

  statment2;

  //.............

  return statmentM;

}
 1. 参数类型省略–绝大多数情况,编译器都可以从上下文环境中推断出lambda表达式的参数类型

 

    

(param1,param2, ..., paramN) -> {

  statment1;

  statment2;

  //.............

  return statmentM;

}
  2. 当lambda表达式的参数个数只有一个,可以省略小括号。lambda表达式简写为:

 

 

param1 -> {

  statment1;

  statment2;

  //.............

  return statmentM;

}
  3. 当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。lambda表达式简化为:

 

 

param1 -> statment
 

 

lambda眼中的this

在lambda中,this不是指向lambda表达式产生的那个SAM(函数接口)对象,而是声明它的外部对象。

 

public class DoFunctionInterfaceByLambda {

    public void doFunctionInterface(FunctionInterfaceDefine functionInterfaceDefine){

        System.out.println(functionInterfaceDefine.functionBody());
    }

    public void testThis(){
        DoFunctionInterfaceByLambda byLambda = this;
        byLambda.doFunctionInterface(()-> {
            System.out.println(this.getClass().toString()); //打印 DoFunctionInterfaceByLambda
            return "doFunctionInterface" ;
        } );
    }
}
 

 


方法引用

 

用语法格式有以下三种:

  • objectName::instanceMethod
  • ClassName::staticMethod
  • ClassName::instanceMethod

前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。

最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。

 

构造器引用

构造器引用语法如下:ClassName::new,把lambda表达式的参数当成ClassName构造器的参数 。例如BigDecimal::new等同于x->new BigDecimal(x)。

 

Streams



 并发编程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值