Java8新特性

发布时间 2023-06-01 14:49:25作者: 笨笨的二黄子

Java8新特性

Java8已经出现了很久了,但是呢,还是有很多人都还在习惯使用以前的来版本JDK,或者是以前老版本的编程方式。通过一段时间对Java8新特性的学习之后,自己也深受感触,原来java8版本写代码可以这么简洁。Java8的新特性给我们编程的过程带来了很多便利,不仅仅是代码量少。更多的还是让程序更简洁,减少代码冗余。Java8新特性中有几个比较主要的特性如下:

  • Lambda 表达式
  • 函数式接口
  • 方法引用
  • 几个新增库Stream流、Optional类

Lambda 表达式

简介

​ Lambda 表达式其实就是一种匿名函数,在这之前大家可能还接触过匿名内部类,虽然也是一种匿名函数,但是它并没有Lambda表达式那么简洁,Lambda表达式的特点就是可以传递,在使用Lambda表达式的时候我们可以将代码像数据一样传递。使用Lambda表达式能够极大的减少我们代码的冗余,而且使用也相当的方便。熟练之后会大大加快我们写代码的速度。

Lambda表达式语法

基础语法

Java8中引入了一个新的操作符“->”该操作符称为箭头操作符或Lambda 操作符

箭头操作符将Lambda表达式拆分成两部分:

左侧:Lambda 表达式参数列表。

右侧:Lambda 表达式中所需要执行的功能,即Lambda 体

示例

1:无参数,无返回值

() ->System.out.println("Hello")

2: 有一个参数,并且无返回值

(e) -> System.out.println(e)

3:若只有一个参数,参数的小括号可以省略

e -> System.out.println(e)

4: 两个以上的参数,又返回值,有多条执行语句

(x,y)-> {

​ System.out.println("Lambda");

​ return Integer.compare(x,y);

​ };

5:如果有两个以上的参数,又返回值,只有一条执行语句,Lambda 体的大括号和return可以省略

Comparator con=(x,y)->Integer.compare(x,y);

6: Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器可以通过上下文推断出数据类型,即“类型推断”

(Integer x,Integery)->Integer.compare(x,y)

函数式接口

简介

是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。我们也可以自定义函数式接口 例如: Java8提供了 @FunctionalInterface 的注解。下面我们详细看下函数式接口。

Java8 提供了4个函数式接口

1. Consumer<T> : 消费型接口    方法:void accep(T t)
2. Supplier<T> : 供给型接口       方法: T get();
3. Function<T,R> : 函数型接口    方法: R apply(T t)
4. Predicate<T> : 断言型接口      方法: boolean Test(T t)
消费型接口: Consumer
@FunctionalInterface
public interface Consumer<T> {

    /**
     * 对给定参数执行此操作
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

使用示例

public class ConsumerCase {
    public static void main(String[] args) {
        Consumer consumer = new Consumer<Object>() {
            @Override
            public void accept(Object o) {
                System.out.println("o = " + o);
            }
        };
        consumer.accept("我是消费式函数接口1");
        consumer.accept("我是消费式函数接口2");
    }
}

供给型接口: Supplier
@FunctionalInterface
public interface Supplier<T> {

    /**
     * 获取一个结果
     */
    T get();
}

使用示例:

public class SupplierCase {
    public static void main(String[] args) {
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "这是一个结果";
            }
        };
        String s = supplier.get();
        System.out.println(s);
        Supplier<List<String>> supplier1 = new Supplier<List<String>>() {
            @Override
            public List<String> get() {
                List<String> arrayList = new ArrayList<>();
                arrayList.add("1");
                arrayList.add("2");
                arrayList.add("4");
                return arrayList;
            }
        };
        List<String> lists = supplier1.get();
        System.out.println(lists);
    }
}
函数型接口: Function
@FunctionalInterface
public interface Function<T, R> {

    /**
     * 将此函数应用于给定的参数。
     */
    R apply(T t);
}

使用示例

public class FunctionCase {
    public static void main(String[] args) {
        // 这里的参数指定string类型,返回值Object类型,根据自己的需要定义参数类型
        Function<String, Object> function = new Function<String, Object>() {
            @Override
            public Object apply(String s) {
                return "传给我的参数是:" + s;
            }
        };
        Object tom = function.apply("大张伟");
        System.out.println(tom);
    }
}
断言型接口: Predicate
@FunctionalInterface
public interface Predicate<T> {

    /**
     * 对参数值进行检验
     */
    boolean test(T t);
}

使用示例:

public class PredicateCase {
    public static void main(String[] args) {
        Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                if("1".equals(s)){
                    return true;
                }
                return false;
            }
        };
        boolean test = predicate.test("2");
        System.out.println("test = " + test);
    }
}

除了以上函数式接口,Java8还对以上函数式接口进行扩展,如下:

两个参数的函数:
BiConsumer<T, U>
BiFunction<T, U, R>
BiPredicate<T, U>
这些函数就不详细介绍了,大家自行根据源码理解。

方法引用

简介

方法引用通过方法的名字来指向一个方法。方法引用可以使语言的构造更紧凑简洁,减少冗余代码。方法引用使用一对冒号 ::

示例

public class MethodReference {

    public static MethodReference create(final Supplier<MethodReference> supplier) {
        return supplier.get();
    }

    public static void collide(final MethodReference methodReference) {
        System.out.println("Collided " + methodReference.toString());
    }

    public void follow(final MethodReference methodReference) {
        System.out.println("Following the " + methodReference.toString());
    }

    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
}

构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下

MethodReference methodReference = MethodReference.create(MethodReference::new);

静态方法引用:它的语法是Class::static_method,实例如下:

cars.forEach(MethodReference::collide);

特定类的任意对象的方法引用:它的语法是Class::method实例如下:

cars.forEach(MethodReference::repair);

特定对象的方法引用:它的语法是instance::method实例如下:

public static void main(String[] args) {
    MethodReference methodReference = MethodReference.create(MethodReference::new);
    final List< MethodReference > cars = Arrays.asList( methodReference );
    MethodReference reference = MethodReference.create(MethodReference::new);
    cars.forEach(reference::follow);
}

Stream流

由于Stream篇幅过长,大家可以阅读另外一篇文章:

https://www.cnblogs.com/zwhdd/p/17448911.html

Optional类

大家可以阅读另外一篇文章: https://www.cnblogs.com/zwhdd/p/17125123.html