侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Java8简明教程

Java  /  管理员 发布于 5年前   598

    Java 8已于2014年3月18日正式发布了,新版本带来了诸多改进,包括Lambda表达式、Streams、日期时间API等等。本文就带你领略Java 8的全新特性。 

一.允许在接口中有默认方法实现

        Java 8 允许我们使用default关键字,为接口声明添加非抽象的方法实现。这个特性又被称为扩展方法。下面是我们的第一个例子: 

package com.bijian.study;interface Formula {    double calculate(int a);     default double sqrt(int a) {        return Math.sqrt(a);    }}

 

        在接口Formula中,除了抽象方法caculate以外,还定义了一个默认方法sqrt。Formula的实现类只需要实现抽象方法caculate就可以了。默认方法sqrt可以直接使用。 

package com.bijian.study;public class FormulaTest {public static void main(String[] args) {Formula formula = new Formula() {    @Override    public double calculate(int a) {        return sqrt(a * 100);    }}; double calRes = formula.calculate(100);     // 100.0System.out.println(calRes);double sqRes = formula.sqrt(16);           // 4.0System.out.println(sqRes);}}

 

        formula对象以匿名对象的形式实现了Formula接口。代码很啰嗦:用了6行代码才实现了一个简单的计算功能:a*100开平方根。我们在下一节会看到,Java 8 还有一种更加优美的方法,能够实现包含单个函数的对象。

 

二.Lambda表达式

        让我们从最简单的例子开始,来学习如何对一个string列表进行排序。我们首先使用Java 8之前的方法来实现:

package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;public class Lambda {public static void main(String[] args) {List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return b.compareTo(a);}});System.out.println(names);//[xenia, peter, mike, anna]}}

 

        静态工具方法Collections.sort接受一个list,和一个Comparator接口作为输入参数,Comparator的实现类可以对输入的list中的元素进行比较。通常情况下,你可以直接用创建匿名Comparator对象,并把它作为参数传递给sort方法。 

        除了创建匿名对象以外,Java 8 还提供了一种更简洁的方式,Lambda表达式。   

package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.List;public class LambdaTest {public static void main(String[] args) {          List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");          Collections.sort(names, (String a, String b) -> {            return b.compareTo(a);        });        System.out.println(names);//[xenia, peter, mike, anna]      }}

 

        你可以看到,这段代码就比之前的更加简短和易读。但是,它还可以更加简短:  

package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.List;public class LambdaTest {public static void main(String[] args) {          List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");          Collections.sort(names, (String a, String b) -> b.compareTo(a));        System.out.println(names);//[xenia, peter, mike, anna]      }}

 

        只要一行代码,包含了方法体。你甚至可以连大括号对{}和return关键字都省略不要。不过这还不是最短的写法: 

package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.List;public class LambdaTest {public static void main(String[] args) {          List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");          Collections.sort(names, (a, b) -> b.compareTo(a));        System.out.println(names);//[xenia, peter, mike, anna]      }}

 

        Java编译器能够自动识别参数的类型,所以你就可以省略掉类型不写。让我们再深入地研究一下lambda表达式的威力吧。 

 

三.函数式接口

        Lambda表达式如何匹配Java的类型系统?每一个lambda都能够通过一个特定的接口,与一个给定的类型进行匹配。一个所谓的函数式接口必须要有且仅有一个抽象方法声明。每个与之对应的lambda表达式必须要与抽象方法的声明相匹配。由于默认方法不是抽象的,因此你可以在你的函数式接口里任意添加默认方法。 

        任意只包含一个抽象方法的接口,我们都可以用来做成lambda表达式。为了让你定义的接口满足要求,你应当在接口前加上@FunctionalInterface 标注。编译器会注意到这个标注,如果你的接口中定义了第二个抽象方法的话,编译器会抛出异常。 

        举例: 

package com.bijian.study;@FunctionalInterface  public interface Converter <F, T> {      T convert(F from);         default double add100(int a) {        return a + 100;    }        default double mul3(double a) {        return a*3;    }}

 

package com.bijian.study;public class ConverterImpl {public static void main(String[] args) {Converter<String, Integer> converter = (from) -> Integer.valueOf(from);  Integer converted = converter.convert("123");  System.out.println(converted);    // 123System.out.println(converter.mul3(converter.add100(converted)));//669.0}}

 

        注意,如果你不写@FunctionalInterface 标注,程序也是正确的。

 

四.方法与构造函数引用

        上面的代码实例可以通过静态方法引用,使之更加简洁:

package com.bijian.study;public class ConverterImpl {public static void main(String[] args) {Converter<String, Integer> converter = Integer::valueOf;Integer converted = converter.convert("123");System.out.println(converted);   // 123}}

 

        Java 8 允许你通过::关键字获取方法或者构造函数的的引用。上面的例子就演示了如何引用一个静态方法。而且,我们还可以对一个对象的方法进行引用: 

package com.bijian.study;public class Something {String startsWith(String s) {        return String.valueOf(s.charAt(0));    }public static void main(String[] args) {Something something = new Something();Converter<String, String> converter = something::startsWith;String converted = converter.convert("Java");System.out.println(converted);    // "J"}}

 

        让我们看看如何使用::关键字引用构造函数。首先我们定义一个示例bean,包含不同的构造方法:

package com.bijian.study;class Person {    String firstName;    String lastName;     Person() {}     Person(String firstName, String lastName) {        this.firstName = firstName;        this.lastName = lastName;    }        public String toString() {    return this.firstName + " " + this.lastName;    }        public static void main(String[] args) {    PersonFactory<Person> personFactory = Person::new;    Person person = personFactory.create("Peter", "Parker");    System.out.println(person);    }}

 

        接下来,我们定义一个person工厂接口,用来创建新的person对象:

package com.bijian.study;interface PersonFactory<P extends Person> {    P create(String firstName, String lastName);}

 

        然后我们通过构造函数引用来把所有东西拼到一起,而不是像以前一样,通过手动实现一个工厂来这么做,如上Person类中的main方法。 

PersonFactory<Person> personFactory = Person::new;Person person = personFactory.create("Peter", "Parker");

        我们通过Person::new来创建一个Person类构造函数的引用。Java编译器会自动地选择合适的构造函数来匹配PersonFactory.create函数的签名,并选择正确的构造函数形式。



  • 上一条:
    java编程思想 --内部类
    下一条:
    Spring调SDK包报java.lang.NoSuchFieldError错误
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在java中实现的脱敏工具类代码示例分享(0个评论)
    • zookeeper安装流程步骤(0个评论)
    • 在java中你背的“八股文”可能已经过时了(2个评论)
    • 在php8.0+版本中使用属性来增加值代码示例(3个评论)
    • java 正则表达式基础,实例学习资料收集大全 原创(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-11
    • 2018-03
    • 2020-03
    • 2023-05
    • 2023-11
    • 2024-01
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客