Java8新特性

概述

java8主要增加了函数式接口(@FunctionalInterface)、lambda表达式、流(stream)。

函数式接口

什么样的接口是函数式接口
1、被注解@FunctionalInterface修饰的,并且只有一个抽象方法的接口叫函数式接口。
2、没有被@FunctionalInterface注解修饰,但是也只有一个抽象方法的接口,也会被编译器认为是函数式接口
3、java8中规定,接口中可以有默认方法(defalut)修饰,和static方法。只要有一个抽象方法,不管这个接口中还有多少的默认方法和静态方法,改接口都是函数式接口。
例如1.8中的Function接口,有2个default方法和一个static方法以及一个抽象的apply方法,所以Function接口依然是一个函数式接口:

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

4、如果一个函数式接口有多个抽象方法,但是除了自己定义的一个抽象方法外,其他的抽象方法都是父类的抽象方法,则这个接口也是函数式接口。
例如:

@FunctionalInterface
interface MyInterface1{
	void apply();
	String toString();
}

这里toString()父类object的方法,不会报错。如果在增加一个自定义的抽象接口,就会报错,不满足函数是借口定义。如:
在这里插入图片描述

lambda表达式与函数式接口的关系。

每一个函数式接口的实现都可以由lambda表达式来创建,所以说lambda表达式的本质是一个接口的实现类,是一个对象,并且定义了函数式接口中的唯一抽象方法的行为。
例如:
可以通过lambda表达式定义一个MyInterface1的实现类,通果控制台打印直到,实例a实现了MyInterface1接口。
在这里插入图片描述在这里插入图片描述

lambda表达式的作用

1、可以将函数作为参数传递给方法,实现行为传递。以前java是值传递,现在可以传递行为(方法),这时一种更高层次的抽象。
例如:
aaa方法的func1参数是一个函数式接口类型,我们可以在调用的时候具体定义指定要执行的行为(排序、大小写转换、求和。。。),以前每一种行为都需要定义一个方法,现在只需要一个函数式接口参数,在调用的时候具体传递行为。这是对方法更高一级的抽象。
在这里插入图片描述
2、使代码更简洁,更容易理解。

lambda表达式的格式

lambda表达式的标准格式:
有三部分
一些参数
一个箭头
一段代码
格式:
(参数列表)->{一些重写方法的代码}
解释说明格式:
()接口中抽象方法的参数列表:没有参数空,有就写,多个用,分割
->传递的意思,把参数传递给方法体{}
{}重写接口的抽象方法的方法体

如果只有一个参数可以省略()
如果{}中只有一个表达式,可以省略{}和return(如果有返回值的话)
如下两者等价:

Function<String, String> func1 = x -> x + "2";
Function<String, String> func2 = (x) -> {return x + "2";};

java8中定义的常见的函数式接口

1、Comsumer 消费型接口
定义一种行为,接收一个类型为T的参数,没有返回值

@FunctionalInterface
public interface Consumer<T> {
    //接收一个方法为T的参数,没有返回值
    void accept(T t); 
    //先执行调用者的accept方法,消费一次t
    //在返回一个持有Consumer<? super T> after的Consumer对象,然后调用accept方     法在消费一次t
    
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Consumer<String> consumer = System.out::println;
consumer.accept("test");

Consumer<String> consumer = x -> System.out.println(x + "1");
consumer.andThen(x -> System.out.println(x + "2")).accept("aa");
//consumer 调用accept返回aa1
//after(就是x -> System.out.println(x + "2"))调用accept返回aa2

2、Supplier :供给型接口
定义一种行为,没有输入,返回一个T类型的返回值

@FunctionalInterface
public interface Supplier<T> {
    //返回一个T类型的参数
    T get();
}

Supplier<UUID> sp = UUID::randomUUID;
System.out.println(sp.get().toString());

3、Function<T,R>:函数型接口
给一个输入参数T,返回一个R类型的返回值

@FunctionalInterface
public interface Function<T, R> {
    //输入t,返回R
    R apply(T t);
    //将before.apply(v)的返回值作为调用者apply方法的参数
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    //将调用者apply的返回值,作为after的apply方法的参数
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

4、Predicate:断言型接口
定义一种断言行为,输入参数T,判断是否满足所定义的行为,返回布尔值。

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

Predicate<String> p =  x -> x.length() > 5;
p.test("abcfrs");

5、BiFunction<T, U, R> :函数类型
定义一种行为,输入两个参数T,U;返回R类型的值

@FunctionalInterface
public interface BiFunction<T, U, R> {
	//输入两个参数,返回R
    R apply(T t, U u);
   //先执行调用者的apply方法啊,返回值R在作为Function after的输入参数 
    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

思考:为什么没有beforce,因为BiFunction和Function返回者只有一个,andThen中的参数只能是Function类型,而beforce只需要一个参数,而输入参数有2个。

注意:这些函数式接口,只是定义一种抽象的行为,可以将这些接口作为方法的参数,具体调用的时候传递具体实现。也就是传递行为或者传递函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值