• jdk8新特性学习总结


    jdk8新增了一下几个新的特性

    • lambda表达式和函数式接口
    • 方法引用
    • stream流

    这里stream流的api比较多在这篇文章就不详细展开了。

    lambda表达式和函数式接口

    lambda表达式

    先简单介绍 一下lambda表达式:lambda表达式也可以称为是闭包,它允许把函数作为一个方法的参数传入到方法中,使用lambda表达式可以使代码更简介美观。

    语法

    我们来看下它的语法格式,很简单清晰

    (入参)->{返回值}
    

    他有如下几个特性

    • 可选类型声明:入参部分传参的时候可以不声明参数类型,编译器能直接统一识别参数类型。
    • 可选参数圆括号:入参部分是一个参数,那么可以把圆括号省略,如果是多个参数圆括号不能省略。
    • 可选大括号:如果打括号里只有一句代码就可以省略大括号。
    • 可选返回关键字:如果大括号内只有一个需要返回的值或则表达式,那么就可以省略return返回关键字。

    使用

    常见的几种写法

    //无参不带括号且不带返回关键字
    ()->1;
    //带返回关键字
    ()->return 1;
    //带大括号
    ()->{return 1};
    //有一个参数带小括号
    (int a)->return a+1;
    //不带小括号(不建议这么写)
    a ->return a+1;
    //多个参数,不写参数类型
    (a,b)->{a+b};
    //有参打印一句话
    (String a)->System.out.printl(a)
    

    大致的写法就是这样,后面会有更详细的用法。
    lambda表达式常常和函数式接口一起使用,那么我们就来了解一下函数式接口

    函数式接口

    函数式接口首先它是个接口,然后这个接口里面有且仅有一个抽象方法,然后在该接口上加一个@FunctionalInterface注解,那么它就是一个函数式接口了。

    语法

    @FunctionalInterface
    public interface FunctionIntfaceDemo {
        String test1();
    }
    

    这样就简单定义了一个函数式接口。

    如何使用

    其实函数式接口可以隐式转换为lambda表达式
    像上面我们定义的那个函数式接口它就可以用lambda表达式这么写

    ()->"返回一个String类型的参数";
    

    或者直接赋值

    FunctionIntfaceDemo test = ()->"返回一个String类型的参数";
    

    java 给我们提前定义好了4个常用的函数式接口
    分别是Functio< R, T>,Consumer,Supplier,Predicate。
    接下来慢慢解释着几个函数的作用。
    这里我们只简单的了解不做深入的讨论

    Function< R,T >

    这个函数它接收一个R对象类型的值,然后返回一个T对象类型的值,然后通过调用apply方法去执行内容。
    我们直接看用法,这里我为了方便大家观察就不去简写lamdba表达式了

    Function<Integer,Integer> s =(Integer a)->{return a+2;};
    Integer apply = s.apply(2);
    

    这里接收的参数必须是对象类型,不能是基础类型。
    这串代码接收了一个integer类型的a,然后返回了一个integer类型的a+2。接着调用了apply传入了一个2,获得了一个结果。

    关于Function的细节部分就不展开了,不然这篇文章就长了

    Consumer

    Consumer是消費者的意思,Consumer< V>就是接收一个V对象的值,然后不返回,本质上就接收的这个对象被消费掉了。然后使用accept去执行。

    Consumer<Integer> consumer = (a)-> System.out.println(a) ;
    consumer.accept(5);
    

    Supplier

    Supplier是提供者的意思,和上面的消費者相反,它不接收参数,Supplier< T>返回一个T对象类型的值。通过调用get方法执行。

    Supplier<String> supplier = () -> "提供产品";
    String s1 = supplier.get();
    

    Predicate

    这个单词翻译过来是谓语的意思,它是一个谓语接口Predicate< T,Boolean>它接收一个T类型的对象然后返回一个布尔值,通过test方法执行。其实它和Function一样,但是为了区分开来所以单独划分了出来。

    Predicate<Integer> predicate = (Integer a) -> a >= 10;
    boolean test1 = predicate.test(15);
    

    其它接口

    其实Java给我们提供了40多种函数接口,前面介绍的是最基础的四种接口。剩下的几个接口都是上面几个接口的变式,大多数都是对参数类型和参数数量做了限制。这里我们分别举一个例子

    参数类型限制的接口:IntToDoubleFunction,接受一个int类型输入,返回一个double类型结果。这里同时限制了入参和返回值。这个就是Function的变种。

    返回值类型限制的接口:DoubleSupplier,代表一个double值结构的提供方,其实它就是Supplier的变种

    数量限制接口:这类接口需要接收两个参数,此类接口的名字前面一般都是Bi开头Binary(二元的意思),比如BiConsumer< T,U>,代表了一个接受两个输入参数的操作,并且不返回任何结果。

    Operator接口:这类接口就是一种简写一般用于两个相同类型的计算,这类型的接口总共就两种(不是两个),分别是一元操作的UnaryOperator< T>,接受一个参数为类型T,返回值类型也为T。和BinaryOperator,代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果。

    方法引用

    方法引用我们可以理解为lambda表达式的另外一种形式具体概念就不多说了。

    方法引用主要有四类,分别是静态方法引用实例方法引用对象方法引用以及构造方法引用

    接下来我们一个一个看他们的使用方法

    我们先看下他们对应的语法格式

    //静态方法引用
    类名::静态方法
    //实例方法引用
    对象实例名::实例方法
    //对象方法引用
    对象名::实例方法
    //构造方法引用
    类名::new
    

    上面这样提现出来可能不是太清晰,我们来具体看一下代码

    代码举例

    这里是列举了上面的语法结构,其实在使用时候可以很灵活。

    public class MethodReferenceDemo {
    
        static void StaticMethodQuote(){
            System.out.println("静态方法引用");
        }
    
        void InstanceMethodQuote(){
            System.out.println("实例方法引用");
        }
    
        MethodReferenceDemo(){
            System.out.println("构造方法的引用");
        }
        public static void main(String[] args) {
            //静态方法引用
            Runnable staticMethodQuote = MethodReferenceDemo::StaticMethodQuote;
            staticMethodQuote.run();
            //实例方法引用
            MethodReferenceDemo methodReferenceDemo = new MethodReferenceDemo();
            Runnable instanceMethodQuote = methodReferenceDemo::InstanceMethodQuote;
            instanceMethodQuote.run();
            //对象方法引用
            Consumer<MethodReferenceDemo> objectMethodQuote = MethodReferenceDemo::InstanceMethodQuote;
            objectMethodQuote.accept(new MethodReferenceDemo());
            //构造方法的引用
            Runnable aNew = MethodReferenceDemo::new;
            aNew.run();
        }
    }
    
    

    我们来看下打印结果

    静态方法引用
    构造方法的引用
    实例方法引用
    构造方法的引用
    对象方法的引用
    构造方法的引用
    

    这里构造方法的引用打印了三次是因为,我们将对象实例化了三次,除了静态方法的引用其余的都调用了构造方法。

    其实上面的方法引用是可以直接转成lambda表达式的
    大致就是这个样子

    //静态方法引用
    Runnable staticMethodQuoteLambda = () -> MethodReferenceDemo.StaticMethodQuote();
    //实例方法引用
    Runnable instanceMethodQuoteLambda = () -> methodReferenceDemo.InstanceMethodQuote();
    //对象方法引用
    Consumer<MethodReferenceDemo> objectMethodQuoteLambda= (objectMethodQuoteParameter)->objectMethodQuoteParameter.ObjectMethodQuote();
    objectMethodQuoteLambda.accept(new MethodReferenceDemo());
    //构造方法引用
    Runnable ConstructionMethodLam = () -> new MethodReferenceDemo();
    

    总结一下大概是这样的

    //静态方法引用
    (参数)->类名.静态方法(参数)
    //实例方法引用
    (参数)->实例名.实例方法(参数)
    //对象方法引用
    (对象,参数)->类名.实例方法(参数)
    //构造方法引用
    (参数)->new 类名(参数)
    

    所以本质上这些东西区别也特别大

    关于stream后面有时间就在专门写一篇总结下。

  • 相关阅读:
    Android之SurfaceView学习(一)
    AS3的加载机制(带例子) 转载
    Timer与TimerTask的用法
    A*寻路初探 GameDev.net (转载)
    解决在Sql Server2005查询分析器中读取Excel表出现的一些问题
    svn更改用户问题
    MVC4 WEBAPI初探
    使用WORD2013发布blog
    一个IIS中可否支持两个版本的Freamwork
    web打印也能分页
  • 原文地址:https://www.cnblogs.com/ccsert/p/12844463.html
Copyright © 2020-2023  润新知