JAVA SE 8 学习笔记(一)lambda表达式

来源:互联网 发布:java 开源 paas 平台 编辑:程序博客网 时间:2024/04/20 20:36

JAVA SE 8 学习笔记 是在学习《写给大忙人看的java se 8》一书后进行复习总结,以备随时查看

如需学习详细内容,请支持正版图书


1. Lamda表达式


Lamda表达式是一段可以传递的代码,可以被执行多次。


语法:(参数..)  -> {表达式}

例:

(String first, String second) -> {if(first.length() < second.length()) return -1; else return 0}


如果参数只有一个可以省略小括号

如果没有参数可以提供一堆空的小括号

如果参数类型可以被推导,那么可以省略参数类型

如果代码块只有一行可以省略大括号


对于只包含一个抽象方法的接口,称为函数式接口,可以通过Lamda表达式创建该接口的对象。

例:

Arrays.sort(words, (first, second) -> Integer.Compare(first.length(), second.length()));


可以在任意函数式接口上标注@FunctionalInterface,这样编译器会检查该实体是否只包含一个抽象方法,并且javadoc页面也会包含一条声明

该注解不要求强制使用,但是会让代码更清楚


方法引用

当想要传递给其他代码的操作,已经有了实现的方法,则可以使用方法引用。可以理解为,针对传递既有方法时的,lamda表达式的简写


语法:

对象::实例方法

类::静态方法

类::实例方法


前两种情况中,方法引用等同于提供方法参数的lamda表达式

例:

Math::pow等同于(x, y) -> Math.pow(x, y);


第三种情况,第一个参数会成为执行方法的对象

例:

String::compareToIgnoreCase等同于(x, y) -> x.compareToIgnoreCase(y);


还可以捕获方法引用中的this/super参数

例:

this::equal 等价于x->this.equals(x)

Thread t = new Thread(super::toString);


构造器引用

构造器引用同方法引用类似,不同的是在构造器引用方法中方法名是new

对于拥有多个构造器的类,会根据上下文选择最合适的构造器

例:

List<String> labels = ..;

Stream<Button> stream = labels.stream().map(Button::new);

List<Button> buttons = stream.collect(Collectors.toList());

此处会调用Button(String)构造器


数组构造器引用可以解决”无法创造一个泛型数组“的问题

Button[] buttons = stream.toArray(Button[]::new);


变量作用域

lambda表达式可以捕获闭合作用域中的变量的值,这些变量称为自由变量。例如可以将lambda表达式转换为一个只含一个方法的对象,此时自由变量的值被复制到该对象的实例中

例:

public static void repeatMessage(String text, int count) {

Runnable r = () -> {

for(int i=0; i< count; i++) {

System.out.println(text);

}

};

new Thread(r).start();

}

在lambda表达式中被引用的变量不可更改,但是变量引用的值可以更改。这不是线程安全的,不建议这么做。

lambda表达式中不允许声明与一个局部变量同名的参数或局部变量


lambda表达式中this代表创建该lambda表达式的方法的this

例:

public class Application {

public void doWork() {

Runnable r = () -> {...; this.toString();}

}

}

此时调用Application的toString()


默认方法

Java SE 8 允许接口包含带有具体实现的方法(称为默认方法)

默认方法遵从以下两个规则:


1. 类优先:当父类中存在与接口中默认方法同名同参数的方法时,父类中的方法会起作用

例:

假设Person, Name中都存在getName()默认方法。

class Student extends Person implements  Named { ... }

此时只有父类方法起作用。类优先可以保证与Java7的兼容性


2. 当实现的两个接口中包含同名同参数的方法时, 编译器会报错,要求开发人员自行实现此方法。(可以在实现中选择调用其中一个接口的方法)

例:

假设Person, Name中都存在getName()默认方法。

解决冲突:

class Student implements Person, Named {

public String getName() { return Person.super.getName(); }

}


接口中的静态方法

Java 8中接口可以添加静态方法,这样就不比再为一个工具方法提供辅助类,并且可以灵活运用函数的强大。

例如List接口提供了一个排序方法,接收一个“键提取”函数

例:

首先,定义compareByNameThenAge方法定义比较的行为
public static int compareByNameThenAge(Human lhs, Human rhs) {
    if (lhs.name.equals(rhs.name)) {
        return lhs.age - rhs.age;
    } else {
        return lhs.name.compareTo(rhs.name);
    }
}
接着使用这个引用去调用humans.sort方法:
humans.sort(Human::compareByNameThenAge);





0 0
原创粉丝点击