jdk1.8新特性
接口增强
接口中default、static关键字可以有方法体,可以实现逻辑
public interface People {
//不需要被实现,当然也可以实现
default void eat(){
System.out.println("我是接口中eat方法,在吃东西");
}
//无法实现
static void dirnk(){
System.out.println("我是接口中dirnk方法,在喝东西");
}
//子类必须实现
void play();
}
base64
public class New {
public static void main(String[] args) throws UnsupportedEncodingException {
String spring = "我们都是神枪手";
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
//编码
String encodeToString = encoder.encodeToString(spring.getBytes("UTF-8"));
System.out.println(encodeToString);
//解码
System.out.println(new String(decoder.decode(encodeToString), "UTF8"));
}
}
日期时间类
LocalDate:不包含具体时间的⽇期。
LocalTime:不含⽇期的时间。
LocalDateTime:包含了⽇期及时间。
package com.example.demo.jdl8;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class DateUtils {
Logger logger = LoggerFactory.getLogger(DateUtils.class);
@Test
public void test() {
LocalDate now = LocalDate.now();
logger.info(String.format("当前时间:%s",now));
logger.info(String.format("现在是哪年:%s",now.getYear()));
logger.info(String.format("现在是哪⽉:%s",now.getMonth()));
logger.info(String.format("现在是哪⽉(数字):%s",now.getMonthValue()));
logger.info(String.format("现在是⼏号:%s",now.getDayOfMonth()));
logger.info(String.format("现在是周⼏:%s",now.getDayOfWeek()));
logger.info(String.format("现在是今年第几天:%s",now.getDayOfYear()));
logger.info("-------------------------------------------------------------");
//localdate 转 date
//获取时间地区ID
ZoneId zoneId = ZoneId.systemDefault();
//转换为当地时
ZonedDateTime zonedDateTime = now.atStartOfDay().atZone(zoneId);
//转为Date类型
Date nows = Date.from(zonedDateTime.toInstant());
logger.info(String.format("转化后的date时间:%s",nows));
//date 转 localdate
Date date = new Date();
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
LocalDate localDate = localDateTime.toLocalDate();
logger.info(String.format("再转化后的local date时间:%s",localDate));
logger.info("-------------------------------------------------------------");
LocalDate changeDate = localDate.plusYears(1);
logger.info("加1年后是哪年:"+changeDate.getYear());
logger.info("旧的是哪年:"+localDate.getYear());
logger.info("判断日期先后: "+changeDate.isAfter(localDate));
logger.info("-------------------------------------------------------------");
LocalDate change = now.withYear(1990);//设置当前日期的年分为1990年
LocalDate localDate1 = change.withMonth(1);//设置当前日期的月份 1月
LocalDate localDate2 = localDate1.withDayOfMonth(1); //设置当前日期的日期为1号
logger.info("修改后的日期: "+localDate2);
LocalDate localDate3 = localDate2.withDayOfYear(360);
logger.info("当前年份360天是哪天: "+localDate3);
//plusYears(long yearsToAdd) LocalDate 当前对象增加指定的年份数
//plusMonths(long monthsToAdd) LocalDate 当前对象增加指定的⽉份数
//plusWeeks(long weeksToAdd) LocalDate 当前对象增加指定的周数
//plusDays(long daysToAdd) LocalDate 当前对象增加指定的天数
//minusYears(long yearsToSubtract) LocalDate 当前对象减去指定的年数
//minusMonths(long monthsToSubtract) LocalDate 当前对象减去注定的⽉数
//minusWeeks(long weeksToSubtract) LocalDate 当前对象减去指定的周数
//minusDays(long daysToSubtract) LocalDate 当前对象减去指定的天数
//compareTo(ChronoLocalDate other) int ⽐较当前对象和other对象在时间上的⼤⼩,返回值如果为正,则当前对象时间较晚,
//isBefore(ChronoLocalDate other) boolean ⽐较当前对象⽇期是否 other对象⽇期之前
//isAfter(ChronoLocalDate other) boolean ⽐较当前对象⽇期是否在 other对象⽇期之后
//isEqual(ChronoLocalDate other) boolean ⽐较两个⽇期对象是否相等
//local date 与字符串转化
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String string = dateTimeFormatter.format(dateTime);
logger.info("local date time 转字符串:"+string);
logger.info("-------------------------------------------------------------");
LocalDateTime date1 = LocalDateTime.of(2020, 1, 1, 1, 1, 1);
logger.info("根据指定年月日时分秒获取LocalDateTime对象:"+date1.toString())
LocalDateTime date2 = LocalDateTime.of(2020,12,1,1,1,1);
logger.info("根据指定年月日时分秒获取LocalDateTime对象:"+date2.toString());
Duration duration = Duration.between(date1,date2);//第⼆个参数减第⼀个参数
logger.info(String.format("两个时间差的天数:%s",duration.toDays()));
logger.info(String.format("两个时间差的⼩时数:%s",duration.toHours()));
logger.info(String.format("两个时间差的分钟数:%s",duration.toMinutes()));
logger.info(String.format("两个时间差的毫秒数:%s",duration.toMillis()));
logger.info(String.format("两个时间差的纳秒数:%s",duration.toNanos()));
}
}
结果
11:04:41.976 [main] INFO com.example.demo.jdl8.DateUtils - 当前时间:2020-09-05
11:04:41.980 [main] INFO com.example.demo.jdl8.DateUtils - 现在是哪年:2020
11:04:41.980 [main] INFO com.example.demo.jdl8.DateUtils - 现在是哪⽉:SEPTEMBER
11:04:41.980 [main] INFO com.example.demo.jdl8.DateUtils - 现在是哪⽉(数字):9
11:04:41.980 [main] INFO com.example.demo.jdl8.DateUtils - 现在是⼏号:5
11:04:41.980 [main] INFO com.example.demo.jdl8.DateUtils - 现在是周⼏:SATURDAY
11:04:41.981 [main] INFO com.example.demo.jdl8.DateUtils - 现在是今年第几天:249
11:04:41.981 [main] INFO com.example.demo.jdl8.DateUtils - -------------------------------------------------------------
11:04:41.984 [main] INFO com.example.demo.jdl8.DateUtils - 转化后的date时间:Sat Sep 05 00:00:00 CST 2020
11:04:41.984 [main] INFO com.example.demo.jdl8.DateUtils - 再转化后的local date时间:2020-09-05
11:04:41.984 [main] INFO com.example.demo.jdl8.DateUtils - -------------------------------------------------------------
11:04:41.985 [main] INFO com.example.demo.jdl8.DateUtils - 加1年后是哪年:2021
11:04:41.985 [main] INFO com.example.demo.jdl8.DateUtils - 旧的是哪年:2020
11:04:41.985 [main] INFO com.example.demo.jdl8.DateUtils - 判断日期先后: true
11:04:41.985 [main] INFO com.example.demo.jdl8.DateUtils - -------------------------------------------------------------
11:04:41.985 [main] INFO com.example.demo.jdl8.DateUtils - 修改后的日期: 1990-01-01
11:04:41.985 [main] INFO com.example.demo.jdl8.DateUtils - 当前年份360天是哪天: 1990-12-26
11:04:41.997 [main] INFO com.example.demo.jdl8.DateUtils - local date time 转字符串:2020-09-05 11:04:41
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - -------------------------------------------------------------
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - 根据指定年月日时分秒获取LocalDateTime对象:2020-01-01T01:01:01
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - 根据指定年月日时分秒获取LocalDateTime对象:2020-12-01T01:01:01
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - 两个时间差的天数:335
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - 两个时间差的⼩时数:8040
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - 两个时间差的分钟数:482400
11:04:41.998 [main] INFO com.example.demo.jdl8.DateUtils - 两个时间差的毫秒数:28944000000
11:04:41.999 [main] INFO com.example.demo.jdl8.DateUtils - 两个时间差的纳秒数:28944000000000000
Optional
主要解决的问题是空指针异常,增加一些兜底方案
public class OptionalUtils {
public static void main(String[] args) {
String s = "Chinese";
Optional<String> optional = Optional.ofNullable(s);
//如果值存在则isPresent()⽅法会返回true
System.out.println(String.format("对象是否为null:%s",!optional.isPresent()));
System.out.println(String.format("对象内容为:%s",optional.get()));
//兜底方法
String s1 = null;
String s2 = "hello world";
String s3 = Optional.ofNullable(s1).orElse(s2);
System.out.println(String.format("s1为空,兜底内容:%s",s3));
Student wangping = null;
Student student = new Student(12,"李萍",2,3);
String s4 = Optional.ofNullable(wangping).map(a -> a.getName()).orElse("默认值");
System.out.println("如果为空就取默认值:"+s4);
String s5 = Optional.ofNullable(student).map(a -> a.getName()).orElse("默认值");
System.out.println("如果不为空就取原值:"+s5);
}
}
result
对象是否为null:false
对象内容为:Chinese
s1为空,兜底内容:hello world
如果为空就取默认值:默认值
如果不为空就取原值:李萍
Lambda表达式
函数式编程:可理解是将⼀个函数作为⼀个参数进⾏传递, 而lambdm表达式会使函数书写更加简洁,我们只需要将lambdm当作参数传递即可。
lambda简单demo
lambda表达式:⼀个接⼝中只包含⼀个⽅法,则可以使⽤Lambda表达式,这样的接⼝称之为“函数接⼝”。接口中最好有@FunctionalInterface注解,防止定义其它方法导致出现问题。
语法:
第⼀部分为括号内⽤逗号分隔的形式参数,参数是函数式接⼝⾥⾯⽅法的参数;
第⼆部分为⼀个箭头符号:->;第三部分为⽅法体,可以是表达式和代码块
参数列表 :
括号中参数列表的数据类型可以省略不写
括号中的参数只有⼀个,那么参数类型和()都可以省略不写
方法体
如果{}中的代码只有⼀⾏,⽆论有返回值,可以省略{},return,分号,要⼀起省略,其他则需要加上
public static void main(String[] args) {
//使用lambdm创建线程
Thread thread = new Thread(() -> System.out.println("线程方法"));
thread.start();
//使用lambdm对集合进行排序
ArrayList<String> strings = Lists.newArrayList("a", "c", "d", "b", "e", "f", "h", "g", "a");
Collections.sort(strings,(a,b)->{
return a.compareTo(b);
});
System.out.println(strings);
}
自定义函数式接口并调用
定义一个接口,函数式接口,只有一个方法,防止出错增加@FunctionalInterface注解。
/**
* 定义一个函数式接口
* 逻辑需要我们自己定义,该接口只是执行
* 我们需要把这个接口当作参数传递,具体逻辑在参数调用时候书写
* @param <T>
* @param <K>
*/
@FunctionalInterface
interface Func<T,K>{
public K get(T t1,T t2);
}
直接上demo,例子中注释已详细说明了函数调用过程。
public class Lambda {
public static void main(String[] args) {
//定义函数式接口中函数的逻辑,需要用它当作参数传递
Func<String,String> func = (a,b)->a.toUpperCase() + "-" + b.toUpperCase();
String s1 = "jack";
String s2 = "jack is a good man";
//形式 1
//String execute = execute((a, b) -> a.toUpperCase() + "-" + b.toUpperCase(), s1, s2);
String execute = execute(func, s1, s2);
System.out.println(execute);
System.out.println("********************************************");
//可以执行很多工具方法的函数,我们我们传递某些工具类
//普通方法的函数调用,调用common包的remove方法,函数式调用
//注意,方法转函数的时候,参数、返回值必须与func(函数式接口)一致
//这个方法符合咱们定义的函数式接口 (string,string) 返回值 (string)
// String remove = StringUtils.remove(s1, s2);
Func<String, String> removeAll = StringUtils::removeAll;
String execute2 = execute(removeAll, s2, s1);
System.out.println("方法的函数调用(删除了s2的jack):"+execute2);
//小技巧
System.out.println("普通方法的函数执行");
TriFunction<Func<String, String>, String, String, String> execute1 = Lambda::execute;
String apply = execute1.apply(func, s1, s2);
System.out.println(apply);
}
/**
* 函数式接口具体方法(执行)
* @param func 函数式参数,函数式编程
* @param s1 代表函数式接口的第一个参数
* @param s2 代表函数式接口的第二个参数
* 当然我们也可以定义其他参数
*/
public static String execute(Func<String,String> func,String s1,String s2){
//对你定义的函数式逻辑执行,就是执行
// Func<String,String> func = (a,b)->a.toUpperCase() + "-" + b.toUpperCase();
String s = func.get(s1, s2);
//可以执行你自己的业务逻辑
//**********************************
//返回
return s;
}
}