JDK8新特性

JDK8是官方发布的一个大版本, 提供了很多新特性功能给开发者使用, 包含语言、编译器、库、工具和JVM等方面的十多个新特性。 本文将介绍编码过程中常用的一些新特性。

一、Lambda 表达式

1.优点

  1. 简化匿名内部类的写法, 允许你以简洁的方式表示可传递给方法或存储在变量中的代码块 ,用更加简洁和表达性的语法来编写匿名函数,从而简化了对函数式接口的实现,使代码更加简洁紧凑。
  2. 提高了代码的可读性和可维护性,尤其是在处理集合、函数式编程等场景下。

当需要启动一个线程去完成任务时,通常会通过 Runnable 接口来定义任务内容,并使用 Thread 类来启动该线程。
传统写法,代码如下:

public class Demo01LambdaIntro {
	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("新线程任务执行!");
			} 
		}).start();
	}
}

Lambda表达式写法,代码如下:
借助Java 8的全新语法,上述 Runnable 接口的匿名内部类写法可以通过更简单的Lambda表达式达到相同的效果。

public class Demo01LambdaIntro {
	public static void main(String[] args) {
		new Thread(() -> System.out.println("新线程任务执行!")).start(); // 启动线程
	}
}

2.Lambda省略格式

在Lambda标准格式的基础上,使用省略写法的规则为:

  1. 小括号内参数的类型可以省略
  2. 如果小括号内有且仅有一个参数,则小括号可以省略
  3. 如果大括号内有且仅有一个语句,可以同时省略大括号、return关键字及语句分号
(int a) -> { 
	return new Person(); 
} 

//省略后
a -> new Person() 

3.使用Lambda的前提条件

Lambda的语法非常简洁,但是Lambda表达式不是随便使用的,使用时有几个条件要特别注意:

  1. 方法的参数或局部变量类型必须为接口才能使用Lambda
  2. 接口中有且仅有一个抽象方法

4.实现原理

匿名内部类在编译的时候会有一个class文件
Lambda在程序运行的时候形成一个类

  1. 在类中新增一个方法,这个方法的方法体就是Lambda表达式中的代码
  2. 还会形成一个匿名内部类,实现接口,重写抽象方法
  3. 在接口的重写方法中会调用新生成的方法.

二、函数式接口

函数式接口在Java中是指:有且仅有一个抽象方法的接口

  1. 是只有一个抽象方法的接口,可以用 Lambda 表达式或方法引用来实现,通常与 Lambda 表达式配合使用, 被 @FunctionalInterface 注解标记,以明确标识函数式接口 。
    例如,java.util.function.Consumer接口就是一个函数式接口,可以接受一个参数并执行某些操作,没有返回值。
  2. JDK 8 提供了一些内置的函数式接口,如 Predicate、Function、Consumer 等,方便进行函数式编程,提高代码的灵活性。

三、方法引用

1.是 Lambda 表达式的一种简化形式, 它可以直接引用已有方法来创建函数式接口的实例 ,进一步简化代码。使代码更加直观,易于理解。

例如,可以使用 “类名::方法名” 的形式来引用静态方法,或者 “对象::方法名” 的形式来引用实例方法。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");  
names.forEach(System.out::println);

2.有不同的引用类型 , 如静态方法引用、实例方法引用、特定类型的实例方法引用和构造方法引用等。

常见引用方式
方法引用在JDK 8中使用方式相当灵活,有以下几种形式:

  1. instanceName::methodName 对象::方法名
  2. ClassName::staticMethodName 类名::静态方法
  3. ClassName::methodName 类名::普通方法
  4. ClassName::new 类名::new 调用的构造器
  5. TypeName[]::new String[]::new 调用数组的构造器

四、Stream流

1.概述

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工
处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

2.优点

1.提供了一种对集合数据进行高效操作的方式,可以进行过滤、映射、排序、聚合等操作, 可以更简洁、高效地处理数据;Stream API 的引入让集合操作变得更加简洁和易于并行处理 。

	//例如:计算一个整数列表中所有偶数的平方和:
     List<Integer> numbers = Arrays.asList(8, 7, 12, 24, 15, 33);
     int sum = numbers.stream()
            .filter(n -> n % 2 == 0)
            .map(n -> n * n)
            .reduce(0, Integer::sum);

2.可以实现并行处理,提高处理大数据集的效率;支持链式调用,将多个操作连接在一起,形成一个数据处理管道 。

3.获取Stream流的两种方式

有以下几种常用的方式:

  • 所有的 Collection 集合都可以通过 stream 默认方法获取流;
  • Stream 接口的静态方法 of 可以获取数组对应的流。

1) 根据Collection获取流

首先, java.util.Collection 接口中加入了default方法 stream 用来获取流,所以其所有实现类均可获取流。

// 集合获取流 
// Collection接口中的方法: default Stream stream() 获取流 
List<String> list = new ArrayList<>(); 
Stream<String> stream1 = list.stream(); 

Set<String> set = new HashSet<>(); 
Stream<String> stream2 = set.stream(); 

Vector<String> vector = new Vector<>(); 
Stream<String> stream3 = vector.stream(); 

java.util.Map 接口不是 Collection 的子接口,所以获取对应的流需要分key、value或entry等情况

// Map获取流 
Map<String, String> map = new HashMap<>(); 
Stream<String> keyStream = map.keySet().stream(); 
Stream<String> valueStream = map.values().stream(); 
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream(); 

2) Stream中的静态方法of获取流

由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法 of ,使用很简单

// Stream中的静态方法: static Stream of(T... values) 
Stream<String> stream6 = Stream.of("aa", "bb", "cc"); 

String[] arr = {"aa", "bb", "cc"}; 
Stream<String> stream7 = Stream.of(arr); 

Integer[] arr2 = {11, 22, 33}; 
Stream<Integer> stream8 = Stream.of(arr2); 

// 注意:基本数据类型的数组不行 
int[] arr3 = {11, 22, 33}; 
Stream<int[]> stream9 = Stream.of(arr3); 

备注: of 方法的参数其实是一个可变参数,所以支持数组

4.Stream常用方法

Stream流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:

  • 中间操作,如 filter(过滤)、map(映射)、sorted(排序)等,这些操作会返回一个新的 Stream,允许进行进一步的操作。
  • 终端操作,如 forEach(遍历)、count(计数)、reduce(归约)等,这些操作会触发 Stream 的执行,并返回一个结果。
方法名 方法作用 返回值类型 方法种类
filter 过滤 Stream 中间操作
limit 取用前几个 Stream 中间操作
skip 跳过前几个 Stream 中间操作
map 映射 Stream 中间操作
concat 组合 Stream 中间操作
count 计数 long 终端操作
forEach 遍历 void 终端操作

Stream注意事项:

  1. Stream只能操作一次
  2. Stream方法返回的是新的流
  3. Stream不调用终结方法,中间的操作不会执行

收集Stream流中的结果

  • 到集合中: Collectors.toList()/Collectors.toSet()/Collectors.toCollection()
  • 到数组中: toArray()/toArray(int[]::new)
  • 聚合计算:Collectors.maxBy/Collectors.minBy/Collectors.counting/Collectors.summingInt/Collectors.averagingInt
  • 分组: Collectors.groupingBy
  • 分区: Collectors.partitionBy
  • 拼接: Collectors.joinging

五、新的日期和时间 API

1.旧版日期时间 API 存在的问题

  1. 设计很差: 在java.util和java.sql的包中都有日期类,java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期。此外用于格式化和解析的类在java.text包中定义。
  2. 非线程安全:java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  3. 时区处理麻烦:日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

2.新的日期和时间API

1)日期和时间类

LocalDate、LocalTime、LocalDateTime类的实例是不可变的对象,分别表示使用 ISO-8601 日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

// LocalDate:获取日期时间的信息。格式为 2019-10-16 
// 创建指定日期 
LocalDate fj = LocalDate.of(1985, 9, 23); 
System.out.println("fj = " + fj); // 1985-09-23 
// 得到当前日期 
LocalDate nowDate = LocalDate.now(); 
System.out.println("nowDate = " + nowDate); // 2019-10-16 
// 获取日期信息 
System.out.println("年: " + nowDate.getYear()); 
System.out.println("月: " + nowDate.getMonthValue()); 
System.out.println("日: " + nowDate.getDayOfMonth()); 
System.out.println("星期: " + nowDate.getDayOfWeek()); 

// LocalTime类: 获取时间信息。格式为 16:38:54.158549300 
// 得到指定的时间 
LocalTime time = LocalTime.of(12,15, 28, 129_900_000); 
System.out.println("time = " + time); 
// 得到当前时间 
LocalTime nowTime = LocalTime.now(); 
System.out.println("nowTime = " + nowTime); 
// 获取时间信息 
System.out.println("小时: " + nowTime.getHour()); 
System.out.println("分钟: " + nowTime.getMinute()); 
System.out.println("秒: " + nowTime.getSecond()); 
System.out.println("纳秒: " + nowTime.getNano()); 

// LocalDateTime类: 获取日期时间信息。格式为 2018-09-06T15:33:56.750 
LocalDateTime fj = LocalDateTime.of(1985, 9, 23, 9, 10, 20); System.out.println("fj = " + fj); // 1985-09-23T09:10:20 
// 得到当前日期时间 
LocalDateTime now = LocalDateTime.now(); 
System.out.println("now = " + now); // 2019-10-16T16:42:24.497896800 
System.out.println(now.getYear()); 
System.out.println(now.getMonthValue()); 
System.out.println(now.getDayOfMonth());
System.out.println(now.getHour()); 
System.out.println(now.getMinute()); 
System.out.println(now.getSecond()); 
System.out.println(now.getNano());

对日期时间的修改,对已存在的LocalDate对象,创建它的修改版,最简单的方式是使用withAttribute方法。withAttribute方法会创建对象的一个副本,并按照需要修改它的属性。以下所有的方法都返回了一个修改属性的对象,他们不会影响原来的对象。

// LocalDateTime类: 对日期时间的修改 
LocalDateTime now = LocalDateTime.now(); 
System.out.println("now = " + now); 

// 修改日期时间 
LocalDateTime setYear = now.withYear(2078); 
System.out.println("修改年份: " + setYear); 
System.out.println("修改月份: " + now.withMonth(6)); 
System.out.println("修改小时: " + now.withHour(9)); 
System.out.println("修改分钟: " + now.withMinute(11)); 
// 再当前对象的基础上加上或减去指定的时间 
LocalDateTime localDateTime = now.plusDays(5); 
System.out.println("5天后: " + localDateTime); 
System.out.println("10年后: " + now.plusYears(10)); 
System.out.println("20月后: " + now.plusMonths(20)); 
System.out.println("20年前: " + now.minusYears(20)); 
System.out.println("5月前: " + now.minusMonths(5)); 
System.out.println("100天前: " + now.minusDays(100));

日期时间的比较

// 日期时间的比较 
// 在JDK8中,LocalDate类中使用isBefore()、isAfter()、equals()方法来比较两个日期,可直接进行比较。 
LocalDate now = LocalDate.now(); 
LocalDate date = LocalDate.of(2018, 8, 8); 
System.out.println(now.isBefore(date)); // false 
System.out.println(now.isAfter(date)); // true 

2)时间格式化与解析

通过 java.time.format.DateTimeFormatter 类可以进行日期时间解析与格式化。

// 日期格式化 
// 得到当前日期时间 
LocalDateTime now = LocalDateTime.now(); 

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 将日期时间格式化为字符串 
String format = now.format(formatter); 
System.out.println("format = " + format); 

// 将字符串解析为日期时间 
LocalDateTime parse = LocalDateTime.parse("1985-09-23 10:12:22", formatter); System.out.println("parse = " + parse); 

3)Instant 类

Instant 时间戳/时间线,内部保存了从1970年1月1日 00:00:00以来的秒和纳秒。

// 时间戳 
Instant now = Instant.now(); System.out.println("当前时间戳 = " + now); 
// 获取从1970年1月1日 00:00:00的秒 
System.out.println(now.getNano()); 
System.out.println(now.getEpochSecond()); 
System.out.println(now.toEpochMilli()); System.out.println(System.currentTimeMillis()); 

Instant instant = Instant.ofEpochSecond(5); 
System.out.println(instant); 

4)计算日期时间差类

Duration/Period类: 计算日期时间差。

  1. Duration:用于计算2个时间(LocalTime,时分秒)的距离
  2. Period:用于计算2个日期(LocalDate,年月日)的距离
// Duration/Period类: 计算日期时间差 

// Duration计算时间的距离 
LocalTime now = LocalTime.now(); 
LocalTime time = LocalTime.of(14, 15, 20); 
Duration duration = Duration.between(time, now); 
System.out.println("相差的天数:" + duration.toDays()); 
System.out.println("相差的小时数:" + duration.toHours()); 
System.out.println("相差的分钟数:" + duration.toMinutes()); 
System.out.println("相差的秒数:" + duration.toSeconds()); 

// Period计算日期的距离 
LocalDate nowDate = LocalDate.now(); 
LocalDate date = LocalDate.of(1998, 8, 8); 
// 让后面的时间减去前面的时间 
Period period = Period.between(date, nowDate); 
System.out.println("相差的年:" + period.getYears()); 
System.out.println("相差的月:" + period.getMonths()); 
System.out.println("相差的天:" + period.getDays()); 

5)时间校正器

有时我们可能需要获取例如:将日期调整到“下一个月的第一天”等操作。可以通过时间校正器来进行。

  • TemporalAdjuster : 时间校正器。
  • TemporalAdjusters : 该类通过静态方法提供了大量的常用TemporalAdjuster的实现。
// TemporalAdjuster类:自定义调整时间

LocalDateTime now = LocalDateTime.now(); 

// 得到下一个月的第一天 
TemporalAdjuster firsWeekDayOfNextMonth = temporal -> { 
	LocalDateTime dateTime = (LocalDateTime) temporal; 
	LocalDateTime nextMonth = dateTime.plusMonths(1).withDayOfMonth(1); 
	System.out.println("nextMonth = " + nextMonth); 
	return nextMonth; 
}; 

LocalDateTime nextMonth = now.with(firsWeekDayOfNextMonth); System.out.println("nextMonth = " + nextMonth); 

6)设置日期时间的时区

Java8 中加入了对时区的支持,LocalDate、LocalTime、LocalDateTime是不带时区的,带时区的日期时间类分别为:ZonedDate、ZonedTime、ZonedDateTime。
其中每个时区都对应着 ID,ID的格式为 “区域/城市” 。例如 :Asia/Shanghai 等。
ZoneId:该类中包含了所有的时区信息。

// 设置日期时间的时区 
// 1.获取所有的时区ID 
ZoneId.getAvailableZoneIds().forEach(System.out::println); 

// 不带时间,获取计算机的当前时间 
LocalDateTime now = LocalDateTime.now(); // 中国使用的东八区的时区.比标准时间早8个小时
System.out.println("now = " + now); 

// 2.操作带时区的类 
// now(Clock.systemUTC()): 创建世界标准时间 
ZonedDateTime bz = ZonedDateTime.now(Clock.systemUTC()); 
System.out.println("bz = " + bz); 

// now(): 使用计算机的默认的时区,创建日期时间 
ZonedDateTime now1 = ZonedDateTime.now(); 
System.out.println("now1 = " + now1); // 2019-10-19T16:19:44.007153500+08:00[Asia/Shanghai] 

// 使用指定的时区创建日期时间 
ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("America/Vancouver")); System.out.println("now2 = " + now2); // 2019-10-19T01:21:44.248794200-07:00[America/Vancouver] 

3.优点

  1. 新版的日期和时间API中,日期和时间对象是不可变的。操纵的日期不会影响老值,而是新生成一个实例。
  2. 新的API提供了两种不同的时间表示方式,有效地区分了人和机器的不同需求。
  3. TemporalAdjuster可以更精确的操纵日期,还可以自定义日期调整器。
  4. 是线程安全的。
  5. 提供了更好的时区支持和日期时间计算功能, 可以轻松地在不同时区之间进行转换 。

六、 接口的默认方法和静态方法

JDK 8以前的接口:

interface 接口名 { 静态常量; 
	抽象方法; 
} 

JDK 8对接口的增强,接口还可以有默认方法和静态方法
JDK 8的接口:

interface 接口名 { 静态常量; 
	抽象方法; 
	默认方法; 
	静态方法; 
} 

在接口中,JDK 8 允许定义默认方法和静态方法,实现了接口的类可以选择继承或重写这些方法,这使得在不破坏现有代码的情况下可以向接口中添加新的方法,方便进行库的升级和扩展。

默认方法可以在接口中提供实现,而不必在实现类中进行实现,这对于接口的向后兼容性非常重要。

1.默认方法

默认方法:接口中可以定义带有实现的方法,称为默认方法(Default Methods)。这使得在不破坏现有实现的情况下,可以向接口中添加新的方法。子类可以选择继承默认方法的实现,或者覆盖默认方法。

接口默认方法的定义格式:

interface 接口名 { 
	修饰符 default 返回值类型 方法名() { 
		代码; 
	} 
} 

2.静态方法

静态方法:接口中可以定义静态方法,类似于类中的静态方法,可以直接通过接口名调用。

接口静态方法的定义格式:

interface 接口名 { 
	修饰符 static 返回值类型 方法名() { 
		代码; 
	} 
} 

3.接口默认方法和静态方法的区别

  1. 默认方法通过实例调用,静态方法通过接口名调用。
  2. 默认方法可以被继承,实现类可以直接使用接口默认方法,也可以重写接口默认方法。
  3. 静态方法不能被继承,实现类不能重写接口静态方法,只能使用接口名调用。
//定义一个接口和其默认方法:
     interface MyInterface {
         void method();default void defaultMethod() {
             System.out.println("This is a default method.");
         }static void staticMethod() {
             System.out.println("This is a static method.");
         }
     }
    
     class MyClass implements MyInterface {
    // 继承了 defaultMethod() 的实现
}MyClass obj = new MyClass();
obj.defaultMethod(); // 输出: Default method
MyInterface.staticMethod(); // 输出: Static method

七、Optional 类

以前对null的处理方式

String userName = "凤姐"; 
// String userName = null; 
if (userName != null) { 
	System.out.println("用户名为:" + userName); 
} else { 
	System.out.println("用户名不存在"); 
} 

1.Optional类介绍

Optional是一个没有子类的工具类,Optional是一个可以为null的容器对象。它的作用主要就是为了解决避免Null检查,防止NullPointerException。
提供了orElse,ifPresent,ifPresentOrElse,map等方法避免对null的判断,写出更加优雅的代码。

2.Optional的基本使用

Optional类的创建方式:

Optional.of(T t) : 创建一个 Optional 实例 
Optional.empty() : 创建一个空的 Optional 实例 
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例

Optional类的常用方法:

isPresent() : 判断是否包含值,包含值返回true,不包含值返回false 
get() : 如果Optional有值则将其返回,否则抛出NoSuchElementException 
orElse(T t) :  如果调用对象包含值,返回该值,否则返回参数t 
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值 
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
// Optional userNameO = Optional.of("凤姐"); 
// Optional userNameO = Optional.of(null); 
// Optional userNameO = Optional.ofNullable(null); 
Optional<String> userNameO = Optional.empty(); 

// isPresent() : 判断是否包含值,包含值返回true,不包含值返回false。 
if (userNameO.isPresent()) { 
	// get() : 如果Optional有值则将其返回,否则抛出NoSuchElementException。 
	String userName = userNameO.get(); 
	System.out.println("用户名为:" + userName); 
} else { 
	System.out.println("用户名不存在"); 
} 

八、重复注解与类型注解

1.重复注解的使用

自从Java 5中引入 注解 以来,注解开始变得非常流行,并在各个框架和项目中被广泛使用。不过注解有一个很大的限制是:在同一个地方不能多次使用同一个注解。JDK 8引入了重复注解的概念,允许在同一个地方多次使用同一个注解。在JDK 8中使用@Repeatable注解定义重复注解。
重复注解的使用步骤:
1.定义重复的注解容器注解

@Retention(RetentionPolicy.RUNTIME) 
@interface 
MyTests { 
	MyTest[] value(); 
} 

2.定义一个可以重复的注解

@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(MyTests.class) 
@interface 
MyTest { 
	String value(); 
} 

3.配置多个重复的注解

@MyTest("tbc") 
@MyTest("tba") 
@MyTest("tba") 
public class Demo01 { 
	@MyTest("mbc") 
	@MyTest("mba") 
	public void test() throws NoSuchMethodException { 

	} 
} 

4.解析得到指定注解

@MyTest("tbc") 
@MyTest("tba") 
@MyTest("tba")
public class Demo01 { 
	@Test 
	@MyTest("mbc") 
	@MyTest("mba") 
	public void test() throws NoSuchMethodException { 
		// 4.解析得到类上的指定注解 
		MyTest[] tests = Demo01.class.getAnnotationsByType(MyTest.class); 
		for (MyTest test : tests) { 
			System.out.println(test.value()); 
		} 
		// 得到方法上的指定注解 
		Annotation[] tests1 = Demo01.class.getMethod("test").getAnnotationsByType(MyTest.class); 
		for (Annotation annotation : tests1) { 
			System.out.println("annotation = " + annotation); 
		} 
	} 
}

2.类型注解的使用

JDK 8为@Target元注解新增了两种类型: TYPE_PARAMETER , TYPE_USE 。
TYPE_PARAMETER :表示该注解能写在类型参数的声明语句中。
TYPE_USE :表示注解可以在任何用到类型的地方使用。

通过@Repeatable元注解可以定义可重复注解,TYPE_PARAMETER 可以让注解放在泛型上, TYPE_USE 可以让注解放在类型的前面

1) TYPE_PARAMETER的使用

@Target(ElementType.TYPE_PARAMETER) 
@interface 
TyptParam { 

} 
public class Demo02<@TyptParam T> { 
	public static void main( String[] args) { 
	
	} 
	public <@TyptParam E> void test( String a) { 
	} 
} 

2) TYPE_USE的使用

@Target(ElementType.TYPE_USE) 
@interface 
NotNull { 

} 
public class Demo02<@TyptParam T extends String> { 
	private @NotNull int a = 10; 
	public static void main(@NotNull String[] args) { 
		@NotNull int x = 1; 
		@NotNull String s = new @NotNull String(); 
	} 
	
	public <@TyptParam E> void test( String a) { 
	
	} 
}

九、Nashorn JavaScript 引擎

JDK 8 引入了 Nashorn,这是一个新的 JavaScript 引擎,用来替代旧的 Rhino 引擎。Nashorn 提供了更好的性能,并且与 JavaScript 语言的最新标准兼容。


import javax.script.*;
 
public class NashornExample {
 
    public static void main(String[] args) throws ScriptException {
 
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
 
        engine.eval("print('Hello from Nashorn')");
 
    }
 
}

十、并行数组操作

JDK 8 通过 Arrays.parallelSort() 方法引入了并行数组排序,这利用了多核处理器来加快排序过程。

int[] numbers = {9, 4, 8, 55, 22,46,72};
 
Arrays.parallelSort(numbers);
 
System.out.println(Arrays.toString(numbers));//输出 [4, 8, 9, 22, 46, 55, 72]

十一、Base64 编码和解码

Java 8的java.util套件中,新增了Base64的类别,可以用来处理Base64的编码与解码,用法如下:

final Base64.Decoder decoder = Base64.getDecoder(); 
final Base64.Encoder encoder = Base64.getEncoder(); 
final String text = "字串文字"; 
final byte[] textByte = text.getBytes("UTF-8"); 
//编码 
final String encodedText = encoder.encodeToString(textByte); System.out.println(encodedText); 
//解码 
System.out.println(new String(decoder.decode(encodedText), "UTF-8"));

你可能感兴趣的:(知识点总结,JavaSE,java,JDK8,javase,八股文,后端)