一、JDK8之default关键字
- 默认方法: 接口里面定义一个默认方法,这个接口的实现类实现了这个接口之后,不用管这个default修饰的方法就可以直接调用,即接口方法的默认实现,(接口名.静态方法)来访问接口中的静态方法。
public interface Animal {
void run();
void eat();
default void breath(){
System.out.println("使用氧气呼吸");
}
static void test(){
System.out.println("这是静态方法");
}
}
二、JDK8之新增base64加解密API
什么是Base64编码:Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法 基于64个字符A-Z,a-z,0-9,+,/的编码方式,是一种能将任意二进制数据用64种字元组合成字符串的方法,而这个二进制数据和字符串资料之间是可以互相转换的,在实际应上Base64除了能将二进制数据可视化之外,也常用来表示字串加密过后的内容。
使用JDK里sun.misc套件下的BASE64Encoder和BASE64Decoder这两个类
缺点:编码和解码的效率比较差,公开信息说以后的版本会取消这个方法
Apache Commons Codec有提供Base64的编码与解码,缺点:需要引用Apache Commons Codec
public class test {
@Test
public void test() throws IOException {
BASE64Encoder encoder = new BASE64Encoder();
BASE64Decoder decoder = new BASE64Decoder();
String text = "旧版编解码";
byte[] textByte = text.getBytes("UTF-8");
//编码
String encodedText = encoder.encode(textByte);
System.out.println(encodedText);
//解码
System.out.println(new String(decoder.decodeBuffer(encodedText),"UTF-8"));
}
}
- Jdk1.8的java.util包中,新增了Base64的类
- 好处:不用引包,编解码销量量远大于 sun.misc 和 Apache Commons Codec
public class test {
@Test
public void test() throws IOException {
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
String text = "JDK8之新编解码";
byte[] textByte = text.getBytes("UTF-8");
//编码
String encodedText = encoder.encodeToString(textByte);
System.out.println(encodedText);
//解码
System.out.println(new String(decoder.decode(encodedText), "UTF-8"));
}
}
三、JDK8之时间日期处理类
- 时间处理再熟悉不过,SimpleDateFormat,Calendar等类
- 旧版缺点: java.util.Date 是⾮非线程安全的 API设计比较差,日期/时间对象比较,加减麻烦
- Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理
- 新增了很多常见的api,如日期/时间的比较,加减,格式化等
- 包所在位置 java.time
- 核心类
LocalDate:不包含具体时间的日期。
LocalTime:不含日期的时间。
LocalDateTime:包含了日期及时间。- 处理时间的API
- JDK8之前:SimpleDateFormat来进行格式化,但SimpleDateFormat并不是线程安全的
- JDK8之后:引入线程安全的日期与时间DateTimeFormatter
- 计算日期时间差 java.time.Duration
import org.junit.Test;
import java.time.*;
import java.time.format.DateTimeFormatter;
public class test {
@Test
public void test() {
LocalDate today = LocalDate.now();
System.out.println(today);
//获取年月日
System.out.println(today.getYear());
System.out.println(today.getMonth());
System.out.println(today.getDayOfMonth());
System.out.println(today.getDayOfWeek());
//加减年份,加厚返回的对象才是修改后的,旧的依旧是旧的
LocalDate changeDate = today.plusYears(1);
System.out.println(changeDate.getYear());
System.out.println(today.getYear());
//日期比较
//是否在之前
System.out.println("isbefore:"+today.isBefore(changeDate));
//是否在之后
System.out.println("isbefore:"+today.isAfter(changeDate));
// jdk8引入 DateTimeFormatter是线程安全的SimpleDateFormat
LocalDateTime lt = LocalDateTime.now();
System.out.println(lt);// 2019-11-07T23:12:29.056
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String ldtStr = dtf.format(lt);
System.out.println(ldtStr);// 2019-11-07 23:12:29
//获取指定时间对象
LocalDateTime ldt = LocalDateTime.of(2020,10,1,10,40,30);
System.out.println(changeDate);// 2020-10-01T10:40:30
//Duration基于时间值,Period基于日期值,
//Duration类表示秒或纳秒时间间隔
//适合处理较短的时间,需要更高的精确性。使用between()方法比较两个瞬间的差:
Instant start = Instant.parse("2019-11-16T11:15:30.00Z");
Instant end = Instant.parse("2019-11-16T11:16:30.00Z");
Duration duration = Duration.between(start,end);//第⼆个参数减第⼀个参数
System.out.println(duration.toDays());//两个时间差的天数
System.out.println(duration.toHours());//两个时间差的⼩时数
System.out.println(duration.toMinutes());//两个时间差的分钟数
System.out.println(duration.toMillis());//两个时间差的毫秒数
System.out.println(duration.toNanos());//两个时间差的纳秒数
//Period 类表示一段时间的年、月、日,使用between()方法获取两个日期之间的差
LocalDate startDate = LocalDate.of(2019, 11, 16);
LocalDate endDate = LocalDate.of(2020, 1, 1);
Period period = Period.between(startDate,endDate);
System.out.println("per:"+period.getYears());//两个时间差的年数
System.out.println("per:"+period.getMonths());//两个时间差的月
}
}
四、JDK8之Optional类
-
Optional 类用处是什么
- 主要解决的问题是空指针异常(NullPointerException)
- 本质是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空
-
创建Optional类
- of()
null 值作为参数传递进去,则会抛异常
Optional<Student> opt = Optional.of(student);
- ofNullable()
如果对象即可能是 null 也可能是非 null,应该使用 ofNullable() 方法
Optional<Student> opt = Optional.ofNullable(student);
- get() 方法
如果值存在则isPresent()方法会返回true,调⽤用get()方法会返回该对象⼀一般使用get之前需要先验证是否有值,不然还会报错
public class Student {
private int age;
public int getAge() {return age; }
public void setAge(int age) {this.age = age;}
}
import java.util.Optional;
public class test {
@Test
public void test(){
Student student = new Student();
Optional<Student> opt = Optional.ofNullable(student);
if(opt.isPresent()){
System.out.println("optional不为空");
Student s = opt.get();
}else {
System.out.println("optional为空");
}
}
- 兜底 orElse方法
orElse()如果有值则返回该值,否则返回传递给它的参数值
@Test
public void test(){
Student student = null;
int result = Optional.ofNullable(student).map(obj->obj.getAge()).orElse(4);
System.out.println(result);
}
五、JDK8之 lambda表达式
- 在JDK8之前,Java是不支持函数式编程的,所谓的函数编程,即可理解是将一个函数(也称为“行为”)作为一个参数进行传递, 面向对象编程是对数据的抽象(各种各样的POJO类),而函数式编程则是对行为的抽象(将行为作为一个参数进行传递)
-
对比创建线程
//JDK8之前创建线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("jdk8之前创建线程");
}
});
//jdk8之后Lambda表达式则只需要使用一句话
new Thread(() -> System.out.println("jdk8之后创建线程"));
-
集合容器里面的字符串排序
//jdk8之前
List<String> list =Arrays.asList("aaa","ggg","ffff","ccc");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
for (String string : list) {
System.out.println(string);
}
//jdk8之后
List<String> list =Arrays.asList("aaa","ggg","ffff","ccc");
Collections.sort(list, (a,b)->b.compareTo(a));
for (String string : list) {
System.out.println(string);
}
- lambda表达式 使用场景(前提):一个接口中只包含一个方法,则可以使用Lambda表达式,这样的接口称之为“函数接口” 语法: (params) -> expression
- 第一部分为括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块
- 参数列列表 :
括号中参数列列表的数据类型可以省略不写
括号中的参数只有一个,那么参数类型和()都可以省略不写- 方法体:
如果{}中的代码只有一行,无论有返回值,可以省略{},return,分号,要一起省略,其他则需要加上
- 好处: Lambda 表达式的实现方式在本质是以匿名内部类的方式进行实现
重构现有臃肿代码,更高的开发效率,尤其是集合Collection操作的时候