学习笔记:黑马程序员Java8新特性

Java语言入门到精通章节

  1. 学习笔记:Java-基础篇(第一部分)_ljtxy.love的博客-CSDN博客
  2. 学习笔记:Java-中级篇(第二部分)_ljtxy.love的博客-CSDN博客
  3. 学习笔记:Java-高级篇(第三部分)_ljtxy.love的博客-CSDN博客
  4. 学习笔记:Java-进阶篇(一)(第四部分)_ljtxy.love的博客-CSDN博客
  5. 学习笔记:Java-进阶篇(二)(第五部分)_ljtxy.love的博客-CSDN博客
  6. 学习笔记:Java8新特性_ljtxy.love的博客-CSDN博客

1.概述

笔记小结:

  1. 概述:JDK1.8所出现的新特性
  2. 新特性:
    • Lambda 表达式
    • 方法引用
    • 默认方法
    • Stream API
    • Date Time API
    • Optional 类
    • ……

1.1含义

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

1.2新特性

  • Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
  • 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  • 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
  • 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
  • Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
  • Date Time API − 加强对日期与时间的处理。
  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
  • Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

说明:

2.Lambda 表达式

笔记小结:

  1. 概述:使代码变的更加简洁紧凑

  2. 语法:

    • 实现的这个接口中的抽象方法中的形参列表 -> 抽象方法的处理
      // 例如
      (parameters) -> expression
      	或
      (parameters) ->{ statements; }
      
  3. 变量作用域:

    • 在Lambda表达式中试图修改被Final关键字修饰的局部变量是不允许的
    • 在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量

2.1概述

​ Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。

2.2语法

​ JDK1.8之后引入的一种语法,他的写法是使用一个->符号,箭头将Lambda表达式分为左右两部分,左边写的是实现的这个接口中的抽象方法中的形参列表,右边就是对抽象方法的处理;

实现的这个接口中的抽象方法中的形参列表 -> 抽象方法的处理
// 例如
(parameters) -> expression
	或
(parameters) ->{ statements; }

说明:

  • **可选类型声明:**不需要声明参数类型,编译器可以统一识别参数值
  • **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号
  • **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号
  • **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值

2.3基本用例

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

参考链接:详解Java中的Lambda表达式_java lambda表达式_明天,你好呀的博客-CSDN博客

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明 -----注意,此处是重写了接口,并用Lambda表达式进行简化后的写法
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
    @FunctionalInterface // 函数式接口注解(只包含一个抽象方法的接口,称为函数式接口)
   interface MathOperation {
      int operation(int a, int b);
   }
    @FunctionalInterface
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

注意:

  • Lambda 表达式主要用来定义行内执行的函数式接口
  • Lambda 表达式免去了使用匿名方法的麻烦,并且给予 Java 简单但是强大的函数化的编程能力

2.4变量作用域

2.4.1成员变量

含义:在Lambda表达式中试图修改局部变量是不允许的

public class Java8Tester {
 
   final static String salutation = "Hello! ";
   // static String salutation = "Hello! ";  可以修改
   // static String salutation = "Hello! ";  可以修改
   
   public static void main(String args[]){
      GreetingService greetService1 = message -> System.out.println(salutation + message);
      // GreetingService greetService1 = message -> System.out.println(salutation ="Test");
      greetService1.sayMessage("Runoob");
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
}

说明:

  • 可以在lambda表达式中访问外层的局部变量
  • 不能在lambda表达式中修改外层的被Final修饰的局部变量

2.4.2局部变量参数

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

String first = "";  
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); 

说明:

​ 编译会出错 ,first已重复定义

3.方法引用

笔记小结:已学,详细参考本套 笔记,Java进阶篇

4.函数式接口

笔记小结:

  1. 概述:函数式接口可以被隐式转换为 lambda 表达式,以简化代码,提高代码的可读性和可维护性。

  2. 函数式接口:

    1. Consumer接口(消费接口)

      Consumer<String> consumer = s -> System.out.println(s);
      consumer.accept("Hello world");
      

      说明:接受一个输入参数,没有返回值

    2. Supplier接口(生产接口)

      Supplier<String> supplier = () -> "Hello world";
      String str = supplier.get();
      System.out.println(str);
      

      说明:接受一个输入参数,返回一个结果

    3. Function接口(函数式接口)

      Function<String, Integer> function = s -> s.length();
      int length = function.apply("Hello world");
      System.out.println(length);
      

      说明:接受一个输入参数,返回一个结果

    4. Predicate接口(断言式接口)

      Predicate<String> predicate = s -> s.length() > 5;
      boolean result = predicate.test("Hello world");
      System.out.println(result);
      

      说明:接受一个输入参数,返回一个布尔值

4.1概述

4.1.1含义

​ 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

4.1.2定义

​ 将@Functionallnterface放在接口之上,如果接口是函数式接口,编译通过;如果不是,编译失败

示例:

@FunctionalInterface
    interface GreetingService {
        void sayMessage(String message);
    }
// 实现
GreetingService greetService1 = message -> System.out.println("Hello " + message);

说明:

​ Lambda表达式的书写方式,需要函数式接口才能进行简写

4.2常用函数式接口

image-20230504102842256

4.2.1Consumer接口

4.2.1.1概述

​ Consumer< T >接口也被称为消费型接口,它消费的数据类型由泛型指定

4.2.1.2常用方法

Consumer< T >:包含两个方法。

  • void accept(T t):对给定的参数执行此操作
  • default Consumer < T > andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
4.2.1.3基本用例
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}
// 例如
Consumer<String> consumer = s -> System.out.println(s);
consumer.accept("Hello world");

说明:

​ 接受一个输入参数,没有返回值

4.2.1.4底层源码

image-20230504103333026

4.2.2Supplier接口

4.2.2.1概述

​ Supplier< T >接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用

4.2.2.2常用方法
  • T get():获得结果
4.2.2.3基本用例
@FunctionalInterface
public interface Supplier<T> {
    T get();
}
// 例如
Supplier<String> supplier = () -> "Hello world";
String str = supplier.get();
System.out.println(str);

说明:

​ 提供一个输出参数,没有输入参数

4.2.2.4底层源码

image-20230504103720208

4.2.3Function接口

4.2.3.1概述

​ Function<T,R>:接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新值

4.2.3.2常用方法
  • R apply(T t):将此函数应用于给定的参数
  • default< V >:Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
4.2.3.3基本用例
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}
// 例如
Function<String, Integer> function = s -> s.length();
int length = function.apply("Hello world");
System.out.println(length);

说明:

​ 接受一个输入参数,返回一个结果

4.2.3.4底层源码

image-20230504104503508

4.2.4Predicate接口

4.2.4.1概述

​ Predicate< T >:接口通常用于判断参数是否满足指定的条件

4.2.4.2常用方法
  • boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
  • default Predicate< T > negate():返回一个逻辑的否定,对应逻辑非
  • default Predicate< T > and():返回一个组合判断,对应短路与
  • default Predicate< T > or():返回一个组合判断,对应短路或
  • isEqual():测试两个参数是否相等
4.2.4.3基本用例
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}
// 例如
Predicate<String> predicate = s -> s.length() > 5;
boolean result = predicate.test("Hello world");
System.out.println(result);

说明:

​ 接受一个输入参数,返回一个布尔值

4.2.4.4底层原理

image-20230504104728281

5.默认方法

笔记小结:

  1. 概述:默认方法就是接口可以有实现方法,而且不需要实现类去强制实现其方法

  2. 语法:

    public interface Vehicle {
       default void print(){
          System.out.println("我是一辆车!");
       }
    }
    
  3. 多个默认方法:若实现多个接口,且接口的方法同名,那么可重写此方法或者通过Super关键字进行指定接口调用

    public class Car implements Vehicle, FourWheeler {
       public void print(){
          Vehicle.super.print();
       }
    }
    
  4. 静态默认方法:静态默认方法,可以直接调用,并且不会强制重写此方法

    public interface Vehicle {
          // 静态方法
       static void blowHorn(){
          System.out.println("按喇叭!!!");
       }
    }
    

5.1概述

5.1.1含义

​ Java 8 新增了接口的默认方法。简单说,默认方法就是接口可以有实现方法,而且不需要实现类去强制实现其方法。我们只需在方法名前面加个 default 关键字即可实现默认方法。

5.1.2作用

​ 进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题

5.2语法

public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}

说明:

​ 在接口中加入default关键字

5.3多个默认方法

当一个类实现了多个接口,并且接口中的方法同名时,可以重写接口方法,或者通过super关键字进行指定调用

// 接口
public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}
 
public interface FourWheeler {
   default void print(){
      System.out.println("我是一辆四轮车!");
   }
}
// 重写接口默认方法
public class Car implements Vehicle, FourWheeler {
   default void print(){
      System.out.println("我是一辆四轮汽车!");
   }
}
// 通过super调用指定接口的默认方法
public class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
   }
}

5.4静态默认方法

public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
    // 静态方法
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}

说明:

  • 接口中的静态方法,可以直接调用

  • 示例:

     Vehicle.blowHorn();
    

6.Stream流

笔记小结:已学,详细参考本套笔记,Java进阶篇

7.Optional 类

笔记小结:

  1. 概述:
    1. 含义:Optional 类是一个可以为null的容器对象
    2. 作用:可以很好的解决空指针异常
  2. 常用成员方法:
    1. 获取Optional对象:
      • ofNullable:如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional
      • of:返回一个指定非null值的Optional
    2. 判断值存在:
      • isPresent :如果值存在则方法会返回true,否则返回 false。
      • isEmpty:如果值不存在则方法会返回true,否则返回 false。
      • orElse :如果存在该值,返回值, 否则返回 other
    3. 获取值:
      • get:如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException

7.1概述

7.1.1含义

​ Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。ptional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

7.1.2作用

Optional 类的引入很好的解决空指针异常

7.2常用成员方法

序号方法 & 描述
1**static Optional empty()**返回空的 Optional 实例。
2**boolean equals(Object obj)**判断其他对象是否等于 Optional。
3**Optional filter(Predicate<? super predicate)**如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
4** Optional flatMap(Function<? super T,Optional> mapper)**如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
5**T get()**如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
6**int hashCode()**返回存在值的哈希码,如果值不存在 返回 0。
7**void ifPresent(Consumer<? super T> consumer)**如果值存在则使用该值调用 consumer , 否则不做任何事情。
8**boolean isPresent()**如果值存在则方法会返回true,否则返回 false。
9**Optional map(Function<? super T,? extends U> mapper)**如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
10**static Optional of(T value)**返回一个指定非null值的Optional。
11**static Optional ofNullable(T value)**如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
12**T orElse(T other)**如果存在该值,返回值, 否则返回 other。
13**T orElseGet(Supplier<? extends T> other)**如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
14** T orElseThrow(Supplier<? extends X> exceptionSupplier)**如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
15**String toString()**返回一个Optional的非空字符串,用来调试

7.3基本用例

import java.util.Optional;
 
public class Java8Tester {
   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      // Optional.ofNullable - 允许传递为 null 参数
      Optional<Integer> a = Optional.ofNullable(value1);
        
      // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> b){
    
      // Optional.isPresent - 判断值是否存在
        
      System.out.println("第一个参数值存在: " + a.isPresent());
      System.out.println("第二个参数值存在: " + b.isPresent());
        
      // Optional.orElse - 如果值存在,返回它,否则返回默认值
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - 获取值,值需要存在
      Integer value2 = b.get();
      return value1 + value2;
   }
}

8.Nashorn JavaScript

笔记小结:Nashorn JavaScript Engine 在 Java 15 已经不可用了,因此详细参考:Java 8 Nashorn JavaScript | 菜鸟教程 (runoob.com)

9.日期时间 API

笔记小结:已学,详细参考本套笔记,Java高级篇

10.Base64编码

笔记小结:

  1. 概述:Base64是一种用于将二进制数据编码为ASCII字符的编码方式
  2. 分类:
    • 基本:
      1. Encoder
      2. Decoder
    • URL:
      1. getUrlEncoder
      2. getUrlDecoder
    • MIME
      1. getMimeEncoder
      2. getMimeDecoder

10.1概述

10.1.1含义

​ 在Java 8中,Base64编码已经成为Java类库的标准。Java8中提供了Base64类来支持Base64编码和解码

10.1.2作用

​ Base64是一种用于将二进制数据编码为ASCII字符的编码方式,常用于在网络传输时将二进制数据转换为可读的字符串

10.1.3分类

Base64工具类提供了一套静态方法获取下面三种BASE64编解码器:

  • **基本:**输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/
  • **URL:**输出映射到一组字符A-Za-z0-9+_,输出是URL和文件
  • **MIME:**输出隐射到MIME友好格式。输出每行不超过76字符,并且使用’\r’并跟随’\n’作为分割。编码输出最后没有行分割

10.2内嵌类

序号内嵌类 & 描述
1static class Base64.Decoder该类实现一个解码器用于,使用 Base64 编码来解码字节数据。
2static class Base64.Encoder该类实现一个编码器,使用 Base64 编码来编码字节数据。

10.3常用成员方法

序号方法名 & 描述
1**static Base64.Decoder getDecoder()**返回一个 Base64.Decoder ,解码使用基本型 base64 编码方案。
2**static Base64.Encoder getEncoder()**返回一个 Base64.Encoder ,编码使用基本型 base64 编码方案。
3**static Base64.Decoder getMimeDecoder()**返回一个 Base64.Decoder ,解码使用 MIME 型 base64 编码方案。
4**static Base64.Encoder getMimeEncoder()**返回一个 Base64.Encoder ,编码使用 MIME 型 base64 编码方案。
5**static Base64.Encoder getMimeEncoder(int lineLength, byte[] lineSeparator)**返回一个 Base64.Encoder ,编码使用 MIME 型 base64 编码方案,可以通过参数指定每行的长度及行的分隔符。
6**static Base64.Decoder getUrlDecoder()**返回一个 Base64.Decoder ,解码使用 URL 和文件名安全型 base64 编码方案。
7**static Base64.Encoder getUrlEncoder()**返回一个 Base64.Encoder ,编码使用 URL 和文件名安全型 base64 编码方案。

10.4基本用例

public class Java8Tester {
    public static void main(String args[]){
        try {
            // 基本编码
            String base64encodedString = Base64.getEncoder().encodeToString("runoobjava8".getBytes("utf-8"));
            System.out.println("Base64 编码字符串 (基本) :" + base64encodedString);

            // 基本解码
            byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);

             // URL 和文件名安全型 编码
            System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-8"));
            base64encodedString = Base64.getUrlEncoder().encodeToString("runoob?java8".getBytes("utf-8"));
            System.out.println("Base64 编码字符串 (URL) :" + base64encodedString);

             // MIME 型 编码
            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i < 10; ++i) {
                stringBuilder.append(UUID.randomUUID().toString());
            }

            byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
            String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
            System.out.println("Base64 编码字符串 (MIME) :" + mimeEncodedString);

        }catch(UnsupportedEncodingException e){
            System.out.println("Error :" + e.getMessage());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值