欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java8新特性

程序员文章站 2022-05-25 11:55:17
...

新增特性

lambda表达式

如果一个接口只有一个抽象方法,则该接口称之为函数式接口,该接口的实现,可以使用lambda表达式,同时还可以给该接口添加@FunctionalInterface 注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的

Lambda表达式可以看成是匿名内部类,使用Lambda表达式时,接口必须是函数式接口
基本语法:

函数式接口 变量名 = (参数1, 参数2…) -> {}

说明:

  1. (参数1, 参数2…)为参数列表, -> 为lambda表达式连接符,{} 内为方法体
  2. 如果形参只有1个,()可以省略,只需要参数的名称即可,如果形参列表为空,只需保留()
  3. 如果执行语句只有1句,{}可以省略,return 可以省略
  4. 形参列表的数据类型会自动推断
  5. lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改该局部变量,会报错

示例:

public interface Computer {
    public int compute(int x, int y);
}
@Test
public void testComputer(){
	Computer plusComputer = (a, b) -> {return a + b;};
	int result = plusComputer.compute(1, 1);
}

// 简写
@Test
public void testComputer(){
	Computer plusComputer = (a, b) -> a + b;
	int result = plusComputer.compute(1, 1);
}

函数式接口

Java8中提供了一些定义好的函数式接口,常用的有

Function

@FunctionalInterface
public interface Function<T, R>{
	R apply(T t);
}

该接口接收一个入参T,返回一个出参R

@Test
public void testFunction(){
	Function<String, String> toUpperFunction = lower -> lower.toUpperCase();
    String upper = toUpperFunction.apply("a");
    System.out.println(upper);//A
}

Consumer

@FunctionalInterface
public interface Consumer<T>{
	void accept(T t);
}

该方法接收一个入参T,无返回值

    @Test
    public void testConsumer() {
        Consumer<String> printConsumer = s -> System.out.println(s);
        printConsumer.accept("test");
    }

Supplier

@FunctionalInterface
public interface Supplier<T>{
	T get();
}

该接口无入参,返回一个出参

@Test
    public void testSupplier() {
        Supplier<TestModel> testModelFactory = () -> new TestModel();
        TestModel testModel = testModelFactory.get();
        System.out.println(testModel);
    }

Predicate

@FunctionalInterface
public interface Predicate<T>{
	boolean test(T t);
}

该接口接收一个入参T,返回一个布尔类型出参

    @Test
    public void testPredicate() {
        Predicate<String> emptyPredicate = s -> s != null && s.length() > 0;
        boolean predicateResult = emptyPredicate.test("abcd");
        System.out.println(predicateResult);
    }

新增类

Optional

空指针是我们最常见也最讨厌的异常,JDK 终于在 Java8 的时候加入了 Optional 类。用于避免空指针的出现,也无需在写大量的if(obj!=null)这样的判断了,前提是你得将数据用Optional装着,它就是一个包裹着对象的容器
Optional 提供三个静态方法来构造一个 Optional:

  1. Optional.of(T value):该方法通过一个非 null 的 value 来构造一个 Optional,返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException
  2. Optional.ofNullable(T value):该方法和 of 方法的区别在于,传入的参数可以为 null
  3. Optional.empty():该方法用来构造一个空的 Optional,即该 Optional 中不包含值

Optional 提供的方法
ifPresent

public void ifPresent(Consumer<? super T> consumer) {
    if (value != null) {
        consumer.accept(value);
    }
}

如果 Optional 中有值,则对该值调用 consumer.accept
orElse

public T orElse(T other) {
    return value != null ? value : other;
}

如果 Optional 中有值则将其返回,否则返回 orElse 方法传入的参数。
orElseGet

public T orElseGet(Supplier<? extends T> ither) {
    return value != null ? value : other.get();
}

orElseGet 与 orElse 方法的区别在于,orElseGet 方法传入的参数为一个 Supplier 接口的实现
orElseThrow

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

orElseThrow 与 orElse 方法的区别在于,orElseThrow 方法当 Optional 中有值的时候,返回值;没有值的时候会抛出异常,抛出的异常由传入的 exceptionSupplier 提供
map

public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent()){
        return empty();
    } else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

如果当前 Optional 为 Optional.empty,则依旧返回 Optional.empty;否则返回一个新的 Optional,该 Optional 包含的是:函数 mapper 在以 value 作为输入时的输出值。
flatMap

public <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent()){
        return empty();
    } else {
        return Objects.requireNonNull(mapper.apply(value));
    }
}

flatMap 方法与 map 方法的区别在于,map 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable 将其包装为 Optional;而 flatMap 要求参数中的函数 mapper 输出的就是 Optional。
filter

public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if(!isPresent()) {
        return this;
    } else {
        return predicate.test(value) ? this : empty();
    }
}

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。

Optional是如果避免空指针异常的呢?
假设现在有个需求:获取id为1的用户名字长度
不使用Optional的做法

User user = queryUserById(1);
if(user != null){
	String userName = user.getName();
	if(userName != null){
		int length = userName.length();
	}
}

使用Optional的做法

int length = Optional(queryUserById(1)).map(user -> user.getName()).map(userName -> userName.length()).orElse(0);

可以看到使用了Optional之后有两个好处

  1. 不会存在忘了判空的情况,因为不需要判空
  2. 没有了层层判空嵌套

Stream

增强特性

相关标签: 应用