JDK1.8的新特性(Lambda表达式等)(一)

一、接口的默认方法

Java 8允许在接口中添加非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法,示例如下:

interface iNews{
    List<News> getAllNews();

    default int aadd(int a){
          return a*100;
    }
}

iNews接口的子类只需要实现getAllNews();这个方法就可以了,默认就会带有getDate()这个方法不需要再实现。

二、Lambda表达式

我先举一个例子,示例代码如下:

  //定义一个stringlist
  List<String> names = Arrays.asList("Lucy","XiaoMing","Mike");
  //排序
  Collections.sort(names,Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return b.compareTo(a);
    }
});

老版本中的做法就是给静态方法Collections.sort方法传入一个list对象还有一个比较器来指定顺序排列。通常做法都是创建一个匿名的比较器对象然后传给sort方法。

但是在Java 8 中就没有必要再这样做了,Java8中提供了更加简洁的方式:Lambda表达式
直接上示例代码:

  //定义一个stringlist
  List<String> names = Arrays.asList("Lucy","XiaoMing","Mike");
  //排序
  Collections.sort(names,(String a,String b) ->{
      return b.compareTo(a);
  });

只用Lambda表达式代码变得更加简洁了,但是还可以变短,示例代码如下:

  //排序
  Collections.sort(name,(String a , String b) -> b.compareTo(a) );

如果函数体只有一行代码,那么可以直接去掉大括号{}还有return关键字,但实际上还可以更短

  //排序
  Collections.sort(name,(a,b) -> b.compareTo(a));

Java编译器可以自动推导出来参数类型,所以你可以不用再写参数类型。

三、函数式接口

Lambda表达式是如何在Java的类型系统中表示的呢?每一个Lambda表达式都表示对应一个类型,通常是接口类型。而函数式接口就是指只有一个抽象方法的接口,每一个该类型的Lambda表达式都会匹配到这个抽象方法。因为默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。
默认方法指的就是Java8中的新特性——给接口添加一个默认方法,具体有在第一点讲到

我们可以将Lambda表达式当做任意一个只包含一个抽象方法的接口类型,确保你的接口达到了这个要求,可以使用一个注解:@FunctionalInterface ,这个注解的作用也是非常简单明了,把这个注解贴在接口上,如果这个接口有多余一个的抽象方法,就会报错。(再直白点,就是贴上了之后,这个接口只能有一个抽象方法,多了就报错)。

实例代码如下:

@FunctionalInterface
interface Converter<F,T>{
  T convert(F from);
}
Converter<String,Integer> converter = (from) -> Integer.valueOf(from);
Integer converter = converter.convert("123");
System.out.println(converter);    //结果为123

四、方法与构造函数

前一节的代码还可以通过静态方法来引用,示例代码如下:

Converter <String,Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted);

Java8允许你使用::关键字来传递方法或者是构造函数的引用,上面的代码引用的是一个静态方法,我们还可以引用一个对象的方法,示例代码如下:

converter = something::startsWith;
String converted = converter.convert("java");
System.out.println(converted);    //j

接下来来试试构造函数的引用,先创建一个具有多个构造函数的简单Java类,示例代码如下:

class Person{
    String name;
    Double money;
}

Person(){
}
Person(String name , Double money){
    this.name = name;
    this.money = money;
}

接下来指定一个用来创建Person对象的对象工厂接口,示例代码如下:

interface PersonFactory<P extends Person> {
    P create(String name, Double money);
}

我们使用构造函数把他们关联起来,而不是实现一个完整的工厂,示例代码如下:

PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("小明",1000.0);

我们使用的时候,只需要用Persion :: new来获取Person类的构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。

五、访问局部变量

我们可以直接在lambda表达式中访问外层的局部变量,示例代码如下:

final int num = 1;
Converter<Integer,String> stringConverter = (from) ->String.valueOf(from+num);
stringConverter.convert("2");    //3

但是这里的 final int num可以不用final 修饰,代码同样正确,但是如果去掉了final的话,num变量就不能被后面的代码修改(其实就是final了),如果被后面的代码修改了,代码就无法被编译。

六、访问对象字段与静态变量

和本地变量不同的是,lambda内部对于实例的字段以及静态变量是又可读又可写。
示例代码如下:

class lambda {
  static int staticNum;
  int num;
  void test(){
    Converter<Integer,String> stringConverter1 = (from) ->{
       staticNum = 123;
       return String.valueOf(from)  
    };
    Converter<Integer,String> stringConverter2= (from) ->{
       num = 123;
       return String.valueOf(from)  
    };
  }
}

七、访问接口的默认方法

还记得第一节的例子吗?一个接口除了抽象方法,还可以定义一个默认方法,这个方法可以被它的实例对象或者是匿名对象访问,但是这个在Lambda中是不行的。
Java8 API提供了很多全新的函数式接口让工作更加方便:

  1. Predicate接口
    Predicate接口只有一个参数,返回boolean类型,其中包含了很多默认方法来组成复杂的逻辑
    示例代码如下:
Predicate<String> predicate = (s) -> s.length() > 0 ;
predicate.test("foo");    //true
predicate.negate().test("foo");     // false

Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;

Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();
  1. Supplier 接口
    Supplier接口返回一个任意范围的值,和Function接口不同的是这个接口没有任何参数
    示例代码如下:
Supplier<Person> personSupplier = Person :: new
personSupplier.get();    //new Person
  1. Consumer接口
    Consumer接口代表在单个参数上执行的操作
    示例代码如下:
Consumer<Person> con = (p) -> System.out.println("Hello,"+p.name);
con.accept(new Person("Lucy",500.0));      //Hello,Lucy
  1. Comparator接口
    Comparator是以前版本中的经典接口,Java8在此之上添加了多种默认方法
    示例代码如下:
Comparator<Person> comparator = (p1,p2) -> p1.name.comparaTo(p2.name);
Person p1 = new Person("小明",100.0);
Person p2 = new Person("小红",100.0);
comparator.compara(p1,p2);
comparator.reversed().compare(p1, p2);
  1. Optional接口
    Optional不是函数是接口,这个是用来防止NullPointerException异常的辅助类型
    Optional被定义为一个简单的容器,其值可能是null或者不是null。在Java8之前一般某个函数应该返回非空对象但是偶尔会返回null,而在Java8中,不推荐你返回null,而是返回Optional
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容