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<E> 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<String> userNameO = Optional.of("凤姐"); 
// Optional<String> userNameO = Optional.of(null); 
// Optional<String> 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"));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值