java8新特性
【说明】:这里只列举了常用的新特性,还有方法引用,Nashorn JavaScript,Java8 Base64
- String类中添加join方法
- lambda表达式
- 函数式接口
- 接口中添加静态方法和默认方法
- Stream流
- Optional类
- 日期时间API
1. String中添加join方法
/**
* java8新特性-String中添加join方法
* 用于拼接字符串
*/
public class NewMehtod {
public static void main(String[] args) {
// 用-连接数字
// 传递可变参数
System.out.println(String.join("-", "1", "2", "3")); // 1-2-3
// 传递数组
String[] strArray = new String[]{"1", "2", "3"};
System.out.println(String.join("-", strArray)); // 1-2-3
// 传递实现Iterator接口的类
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
System.out.println(String.join("-", list)); // 1-2-3
}
}
2.lambda表达式
/**
* java8新特性-lambda表达式
*/
public class Lambda {
public static void main(String[] args) {
// 匿名内部类的方式
Action action = new Action(new Flyable() {
@Override
public void fly() {
System.out.println("普通方法飞行");
}
});
action.start();
// lambda方式
Action action1 = new Action(()->System.out.println("lambda方式飞行"));
action1.start();
}
}
interface Flyable {
void fly();
}
class Action {
private Flyable flyable;
public Flyable getFlyable() {
return flyable;
}
public void setFlyable(Flyable flyable) {
this.flyable = flyable;
}
public Action(Flyable flyable) {
this.flyable = flyable;
}
public void start() {
flyable.fly();
}
}
lambda表达式中使用外部的局部变量默认是final的,不可以在重写方法中改变变量的值。
3.函数式接口
只有一个抽象方法
/**
* java8新特性-函数式接口
*/
public class FunctionInterface {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
eval(list, new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer > 2;
}
});// 3
eval(list,n->n>1);// 2 3
}
/**
* 打印list中满足条件的数
*
* @param list
* @param predicate 只有一个抽象方法的接口(函数式接口)
*/
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
list.forEach(item -> {
if (predicate.test(item)) {
System.out.println(item + " ");
}
});
}
}
【20220403补充】
函数式接口标识:@FunctionalInterface
1.三种类型:
-
- Supplier 供给型函数
@FunctionalInterface
public interface Supplier<T>{
T get();
}
- 2.Consumer 消费型函数
@FunctionalInterface
public interface Consumer<T>{
void accept(T t);
}
- 3.Runnable 无参无返回值型函数
@FunctionalInterface
public interface Runnable{
void run();
}
- 4.Function 有参有返回值型函数
@FunctionalInterface
public interface Function(T,R){
R apply(T t);
}
2.工作中经常会遇见以下情况
- 处理抛出异常的if
- 处理if分支
- 存在值则执行消费操作,不存在执行值为空的操作
2.1 处理抛出异常的if
思想:将if语句和抛出异常封装到工具类和接口中
- 创建异常抛出接口
@FunctionalInterface
public interface ThrowExceptionFunction(){
void throwException(String message);
}
- 创建工具类
public final class VUtils{
private VUtils(){}
public static ThrowException isTrue(boolean b){
return (message)->{
if(b){
throw new RuntimeException(message);
}
}
}
}
- 使用
User user = null;
VUtils.isTrue(!Optional.ofNullable(user).isPresent()).throwException("用户信息不能为空")
2.2 处理if分支操作
思路和2.1一样,将if,else的操作分装到工具类中,执行的方法封装到函数式接口中
1.创建分支接口
@FunctionalInterface
public interface BranchHandleException{
void trueOrFalseHandle(Runnable trueHandle,Runnable falseHandle);
}
- 工具类中添加方法
public static BranchHandleException isTrueOrFalse(boolean b){
// 返回新创建的匿名内部类
return (trueHandle,falseHandle)->{
if(b){
trueHandle.run();
}else{
falseHandle.run();
}
}
}
3.使用
String str = "函数式接口真有趣";
VUtils.isTrueOrFalse(str.length()>0).trueOrFalseHandle(
()->{
System.out.println("字符串长度大于0");
},()->{
System.out.println("字符串长度为0");
}
);
2.3存在值则执行消费操作,否则执行空的操作
- 创建值与非空值的分支处理接口
@FunctionalUbterface
public interface PresentOrElseHandler{
void presentOrElseHandle(Consumer<? super T action,Runnable emptyAction);
}
- 在工具类中添加方法
public static presentOrElseHandler isBlankOrNotBlank(String str){
return (consumer,runnable)->{
if(StringUtils.isNotBlank(str)){
consumer.accept(str);
}else{
runnable.run();
}
}
}
- 使用
String str = null;
VUtils.isBlankOrNotBlank(str).presentOrElseHandle(System.out::println,()->{
System.out.println("空字符串");
})
4.接口中添加静态方法和默认方法
类可以重写接口中的抽象方法和默认方法,不能重写静态方法,如果重写静态方法,那么接口中的静态方法将会被隐藏
public class NewMethodInInterface {
public static void main(String[] args) {
TestClass testClass = new TestClass();
testClass.abTest();// 重写抽象方法
testClass.deTest();// 重写默认方法
TestInterface.stTest();// 静态方法
}
}
interface TestInterface{
// 抽象方法
void abTest();
// 静态方法
static void stTest(){
System.out.println("静态方法");
}
// 默认方法
default void deTest(){
System.out.println("默认方法");
}
}
class TestClass implements TestInterface{
@Override
public void abTest() {
System.out.println("重写抽象方法");
}
@Override
public void deTest() {
System.out.println("重写默认方法");
}
}
5.Stream流
对元素队列进行聚合操作
/**
* java8新特性-Stream流
*/
public class StreamTest {
public static void main(String[] args) {
// forEach打印十个随机数 limit打印十条
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
// map输出元素乘2后的结果 filter筛选出符合大于15的数字
List<Integer> list = Arrays.asList(1, 34, 6, 5, 7, 8);
list.stream().map(i -> i * 2).filter(i -> i > 10).forEach(i-> System.out.println(i));
// sortd进行排序
List<Integer> list1 = Arrays.asList(4, 3, 6, 7, 2, 3, 9);
list1.stream().sorted().forEach(i-> System.out.println(i));
// Collectors返回列表或字符串
List<String> list2 = Arrays.asList("23", "fd", "e5r");
String tr = list2.stream().collect(Collectors.joining("tr"));
String tr1 = String.join("tr", list2);
System.out.println(tr);
System.out.println(tr1);
}
}
6.Optional类
用于判空,防止空指针异常
/**
* java8新特性-Option类
* 判空,获取值等操作,有效防止空指针异常
*/
public class OptionalTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 5, 7, 6);
List<Integer> nullList = null;
// 会抛出空指针异常
// Optional<List<Integer>> nullOption = Optional.of(nullList);
// 不会抛出控制针异常
Optional<List<Integer>> option = Optional.ofNullable(nullList);
Optional<List<Integer>> list1 = Optional.ofNullable(list);
// 判断是否为null
if(list1.isPresent()){
// toString 方法一般用来调试
System.out.println(list1.toString());// Optional[[1, 2, 5, 7, 6]]
// get 获取值
List<Integer> list2 = list1.get();
list2.forEach(System.out::print); // 12576
System.out.println();
}
// 如果为null使用orElse获取 如果不为空则返回值,否则返回设定值
List<Integer> list3 = list1.orElse(Arrays.asList(8, 7));// 12576
List<Integer> list4 = option.orElse(Arrays.asList(8, 7));// 87
list3.forEach(System.out::print);
System.out.println();
list4.forEach(System.out::print);
}
}
7.日期时间API
java7中java.util.Date和java.util.Calendar易用性差,不支持时区,并且是可变的,意味着他们是不安全的
- Instant:瞬时实例
- LocalDate:本地日期
- LocalTime:本地时间
- LocalDateTime:组合了日期和时间
- ZoneDateTime:最完整的日期时间
- ZoneOffSet和ZoneId:解决了时区问题
- DateTimeFormatter:日期和字符串之间转换
/**
* java8新特性-日期时间API
*/
public class DateTimeTest {
public static void main(String[] args) {
// 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);// 2022-02-18T23:15:36.698
// 获取当前时间绝对秒
Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
long epochSecond = instant.getEpochSecond();
System.out.println(epochSecond);// 1645197336
// 获取当前日期
LocalDate localDate = now.toLocalDate();
System.out.println(localDate);// 2022-02-18
// 获取当前时间
LocalTime localTime = now.toLocalTime();
System.out.println(localTime);// 23:15:36.698
// 日期与字符串相互转换
// 日期转字符串
String pattern = "yyyy-MM-dd";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
String format1 = now.format(dateTimeFormatter);
System.out.println(format1);// 2022-02-18
// 字符串转日期
String datetimeText = "1965-02-12";
LocalDate parse = LocalDate.parse(datetimeText,dateTimeFormatter);
System.out.println(parse);// 1965-02-12
}
}