java8新特性学习(一)

223 阅读5分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

java8新特性

Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。

Java 17 LTS is the latest long-term support release for the Java SE platform. JDK 17 binaries are free to use in production and free to redistribute, at no cost, under the Oracle No-Fee Terms and Conditions.

JDK 17 will receive updates under these terms, until at least September 2024.

Java 17 LTS 是 Java SE 平台的最新长期支持版本。

目前大多数企业开发使用最多的仍然是jdk8版本,所以作为一名java开发人员学习jdk8的新特性是很有必要的,可以让你的工作更高效。

新特性有哪些?

java8的新特性有很多,我们一起来学习其中的部分新特性吧。

首先我们查看自己电脑环境的jdk版本:

使用java -version命令,我的版本为1.8.0_211

$ java -version java version "1.8.0_211" Java(TM) SE Runtime Environment (build 1.8.0_211-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

1.Lambda表达式

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。

->操作符是Lambda操作符

左侧:Lambda表示式的参数列表 右侧:Lambda表达式中所要执行的功能

语法格式:

创建一个线程执行输出hello world,传统写法:

public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world");
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

lambda表达式写法:

public static void main(String[] args) {
        Thread thread = new Thread(()->{
            System.out.println("hello world");
        });
        thread.start();
    }

为什么Runnable允许这样写,因为接口只有一个run方法,无参数,无返回值

image-20220125103010058.png

  • 无参数无返回值

创建一个Test接口,声明一个doSomething方法无参无返回值

public interface Test {

    void doSomething();

}

测试一下:

 public static void main(String[] args) {
        Test test = ()->{
            System.out.println("say hello");
        };
        test.doSomething();
    }

输出结果:

say hello

  • 有一个参数无返回值

创建一个Test2接口,声明一个doSomething方法有一个参数无返回值

public interface Test2 {
    void doSomething(int a);
}

调用测试,只有一个参数()可以省略

Test2 test2 = (b)->{
    System.out.println(b);
};
test2.doSomething(10);

输出结果:

10

  • 多个参数无返回值
public interface Test2 {
    void doSomething(int a,int b);
}
 Test2 test2 = (a,b)->{
     System.out.println(a+b);
 };
test2.doSomething(10,20);

输出结果:

30

  • 有返回值,使用return返回结果
public interface Test2 {
    int doSomething(int a,int b);
}
 Test2 test2 = (a, b) -> {
     return a + b;
 };
System.out.println(test2.doSomething(10, 20));

lambda表达式的重要特征:

  • **可选类型声明:**不需要声明参数类型,编译器可以统一识别参数值。
  • **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号。
 Test test = ()-> System.out.println("say hello");
  • **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

image-20220125114019294.png

在局部如果修改编译器会检查报错,如果不修改,即使没有使用final修饰也不会报错。lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)。

在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

2.方法引用

方法引用通过方法的名字来指向一个方法。

方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用使用一对冒号 ::

Test2 test2 = (a, b)->{
    return a + b;
};
System.out.println(test2.doSomething(10, 20));

比如这里的return a+b,就可以使用Integer::sum,代码看起来更加简洁

Test2 test2 = Integer :: sum;
System.out.println(test2.doSomething(10, 20));

3.函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为 lambda 表达式。

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

如定义了一个函数式接口如下:

@FunctionalInterface
public interface Test {

    void doSomething();

}

那么我就可以使用下面这种方式实现doSomething函数

Test test = ()-> System.out.println("say hello");

函数式接口实例

  • Predicate

java.util.function.Predicate 接口定义了一个名叫 test 的抽象方法,它接受泛型 T 对象,并返回一个boolean值。在对类型 T进行断言判断时,可以使用这个接口。通常称为断言性接口 。

输出1-10以内的偶数

 Predicate<Integer> pre = (num)-> num%2==0;

for (int i=1;i<=10;i++){
    if(pre.test(i)){
        System.out.println(i);
    }
}

结果:

image-20220125200934767.png

  • Consumer

java.util.function.Consumer接口定义了一个名叫 accept 的抽象方法,它接受泛型T,没有返回值(void)。如果需要访问类型 T 的对象,并对其执行某些操作,可以使用这个接口,通常称为消费性接口。

使用Consumer实现集合遍历操作:

Consumer<List<String>> con = (list)->{
        for (String s:list){
            System.out.println(s);
        }
};

List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("jcuser");

con.accept(list);

输出结果:

image-20220125201549308.png

  • Function

java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。如果需要定义一个Lambda,将输入的信息映射到输出,可以使用这个接口(比如提取苹果的重量,或把字符串映射为它的长度),通常称为功能性接口。

使用Function实现用户密码 Base64加密操作:

Function<String,String> fun =(password)-> Base64.getEncoder().encodeToString(password.getBytes());

System.out.println(fun.apply("jcuser"));

输出结果:

amN1c2Vy

  • Supplier

java.util.function.Supplier接口定义了一个get的抽象方法,它没有参数,返回一个泛型T的对象,这类似于一个工厂方法,通常称为功能性接口。

使用Supplier创建学生对象

Supplier<Student> supplier = ()-> {
    Student student = new Student();
    student.setName("张三");
    return student;
};

System.out.println(supplier.get());
}

以上就是今天的java8新特性学习实践,下期我们再一起学习其他特性吧,欢迎点赞评论发表看法观点。