目录
一、java 8 新特性
-
Lambda表达式
-
匿名内部类: 使用条件:当需要实现的接口有且仅有一个抽象方法时,我们就可以将实现接口的代码替换为 (方法的参数名)->方法的实现逻辑
如:实现Runnable的匿名内部类:
本来我们要想实现一个Runnable匿名内部类并且创建一个线程,我们需要完整的实现run方法再创建线程:
public class Main { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("不使用lambda表达式"); } }); thread.start(); } }
由于只需要实现一个方法,因此可以使用lambda表达式,run方法没有参数因此lambda表达式也不需要参数,可以写为下面的代码大幅缩减代码的编写量
public class Main { public static void main(String[] args) { Thread thread = new Thread(() -> {System.out.println("使用lambda表达式")}); thread.start(); } }
并且匿名内部类会单独编译成一个class文件,而lambda表达式不会。但是lambda表达式只支持接口,不能支持抽象类。
当参数只有一个时,也可以省略()只留参数名字,并且实现语句只有一句时也可以省略{}。
举个例子,我们创建一个接口
public interface Interface { void method(int i); }
实现它,直接省略()和{},当然,只有参数有且仅有一个时才可以省略(),实现语句有且仅有一条时才能省略{}
public class Main { public static void main(String[] args) { Interface inter = i -> System.out.println(i); inter.method(1); } }
总结:lambda表达式仅能用于接口不能用于抽象类,并且接口中必须有有且仅有一个方法需要实现才可以使用。在使用时,使用的形式如([参数名1,参数名2.....]) -> {实现语句},当参数有且仅有一个时可以省略(),当实现语句有且仅有一个时可以省略{}
-
-
基于lambda表达式的函数式接口(@FunctionalInterface)
-
Supplier供给型函数时接口 仅有一个需要实现的get()方法用于获取需要的对象,返回值是泛型类,如下:当需要一个新的学生对象时调用get方法即可
public class Main { public static void main(String[] args) { Supplier<Student> studentSupplier = () -> new Student(); studentSupplier.get().supplier(); } public static class Student { public void supplier(){ System.out.println("学生类供给式函数式接口"); } } }
-
Consumer消费型函数式接口 仅有一个需要实现的accept(T)方法用于获取需要的对象,返回值是void型,传入的参数用于消费
public class Main { public static void main(String[] args) { Consumer<Student> studentConsumer = student -> System.out.println(student+"已被消费"); studentConsumer.accept(new Student()); } public static class Student { } }
还有一个默认实现了的andThen(Consumer)方法,如果这个方法传入的Consumer参数是空就会抛异常,如果不为空就会在执行完accept后执行,同一个消费型函数时接口对象只能同时调用一次accept方法,但是可以多次调用andThen方法,他们会顺序执行,且该方法只会在accept方法执行完成后执行,单独调用不会执行
public class Main { public static void main(String[] args) { Consumer<Student> studentConsumer = student -> System.out.println(student+"已被消费"); studentConsumer .andThen(student -> System.out.println("消费完成1!")) .andThen(student -> System.out.println("消费完成2!")) // .accept(new Student()) 连续调用报错 .accept(new Student()); } public static class Student { } }
-
Function函数型函数式接口 仅有一个需要实现的apply(T)方法,返回值是泛型类R
public class Main { public static void main(String[] args) { //举例:接收的T类型为Integer类型,返回的R类型为String类型 Function<Integer,String> studentFunction = (num) -> String.valueOf(num); System.out.println(studentFunction.apply(1)); } }
默认实现的compose(Function)方法,此方法在调用时会先将传入apply的参数进行操作然后再执行apply方法,andThen(Function)方法会在最后在对apply方法处理后的返回值进行处理
public static void main(String[] args) { Function<Integer,String> studentFunction = (num) -> String.valueOf(num); //compose方法先将传入的参数转化为Integer类型,然后将Integer类型通过apply方法转化为String类型,最后通过andThen方法将String类型转化为Integer类型 //即 String -> Integer -> String -> Integer System.out.println( studentFunction .andThen((String i)-> i.length()) .compose((String str)->str.length()) .apply("lbw nb") ); //"lbw nb" -> 6 -> "6" -> 1 }
identity将传入的参数原样返回,个人认为没什么用,感兴趣的可以自己看一下
-
Predicate断言型函数式接口 仅有一个需要实现的方法test(T),返回值为boolean
public static void main(String[] args) { Predicate<Integer> stringPredicate = (num) -> num >= 17; Integer num = 17; if(stringPredicate.test(num)){ System.out.println("十七张牌你能秒我,我直接把这个电脑吃掉"); }else { System.out.println("全体起立"); } }
and(Predicate)方法,和test同时满足时才为true
public static void main(String[] args) { Predicate<Integer> integerPredicate = (grade) -> grade >= 60; //and方法,如果和test同时满足 if(integerPredicate .and((Integer grade) -> grade >= 90) .test(70)){ System.out.println("90分,高手"); } }
or(Predicate)放啊,和test有一个满足为true
public static void main(String[] args) { Predicate<Integer> integerPredicate = (num) -> num == 0; //or(Predicate)方法,和grade有一个满足即可 if(integerPredicate .or((Integer i) -> i > 0) .test(17)){ System.out.println("让我猜一猜,这个数是一个非负数"); } }
negate,将test方法结果取反
public static void main(String[] args) { Predicate<Integer> integerPredicate = (num) -> num == 0; //negate方法,会将test方法的结果取反 System.out.println(integerPredicate .negate().test(0)); }
-
-
判空包装类Optional类:处理空指针异常
of(T)方法传入一个参数包装,如果参数为null会报异常,ofNullable(T)如果传入参数为null,不会报异常
ifPresent(Consumer)方法,如果包装的不为null,实现消费型函数式接口来消费传入的参数
public static void main(String[] args) { method("字符串"); method(null); } public static void method(String str) { Optional .ofNullable(str) .ifPresent(s-> System.out.println(s)); }
get()方法获取包装的对象,如果包装的是空,get方法会报异常
public static void main(String[] args) { System.out.println(method("字符串")); System.out.println(method(null)); } public static String method(String str) { return Optional .ofNullable(str) .get(); }
orElse(T)方法,如果包装的是空,就传入参数T并返回T
public static void main(String[] args) { System.out.println(method("字符串")); System.out.println(method(null)); } public static String method(String str) { return Optional .ofNullable(str) .orElse("重新包装"); }
orElseGet(Supplier),如果包装的是空,就传入supplier然后经过操作后再返回一个值
public static void main(String[] args) { System.out.println(method("字符串")); System.out.println(method(null)); } public static String method(String str) { return Optional .ofNullable(str) .orElseGet(()-> "重新包装"); }
orElseThrow(Exception)如果包装的是空,会抛出传入的异常
还有一些其他的方法,感兴趣的可以自己学习
还有一些其他的不常用改进,感兴趣的可以再自行查阅
二、java 9 新特性
-
模块机制
-
JShell交互式编程 在命令行窗口中输入jshell,就可以在命令行窗口中进行java代码编写,vars用于看变量的定义,methods用于看方法的定义,感兴趣的话其他的命令可以自行学习
-
接口中的私有方法 我们知道,java8中的接口只能有常量、抽象方法、静态方法和default方法,如果我们在接口中的default方法和静态方法中需要频繁的使用一些代码,但这些代码我们又不想让子类看到,怎么办呢?在java9中给接口增加了私有方法,让我们可以实现代码的复用同时又不让子类看到,私有方法在接口中必须实现。
-
集合类新增工厂方法 在java9之前,我们要想给集合类里面提前加一些数据,必须要先进行集合类的定义和初始化,然后才能一个个添加如:
public class Main { public static void main(String[] args) { HashMap<Integer,String> hashMap = new HashMap(); hashMap.put(1,"1"); hashMap.put(2,"2"); } }
现在增加了工厂方法,可以直接通过of方法来提前添加,但是注意提前添加的元素无法进行修改,对其他的集合也是这样
public class Main { public static void main(String[] args) { Map<Integer,String> map = Map.of(1,"1",2,"2",3,"3"); } }
-
改进 stream API
-
of改进
将集合进行过滤和去重后收集,此时of中传入null会报错
public class Main { public static void main(String[] args) { List<Integer> list = Stream.of(1,2,3,4) .filter(t->t.equals("3")) .distinct() .collect(Collectors.toList()); } }
改进后使用ofNullable可以允许传入null,但是每次只能一个传入一个
public class Main { public static void main(String[] args) { Stream .ofNullable(null) .forEach(System.out::println); } }
-
iterate limit改进更加类似于for循环 往流中不断的加入一些元素
public class Main { public static void main(String[] args) { Stream .iterate(0,i->i+1) .limit(20) .forEach(System.out::println); } }
改进后可以直接限制次数
public class Main { public static void main(String[] args) { Stream .iterate(0,i -> i < 20,i -> i+1) .forEach(System.out::println); } }
-
新增对数据的截断操作
takewhile 当满足条件时在进行操作
public class Main { public static void main(String[] args) { Stream .iterate(0, i -> i < 20, i -> i + 1) .takeWhile(i -> i < 10) .forEach(System.out::println); } }
dropwhile 当满足条件时不操作
public class Main { public static void main(String[] args) { Stream .iterate(0, i -> i < 20, i -> i+1) .dropWhile(i -> i < 10) .forEach(System.out::println); } }
-
-
try-with-resource
在java9之前,我们要将需要关闭的资源的定义和初始化全部放入try()中才可以,java9中我们可以先定义和初始化,再将需要关闭的资源的变量名放入到try()中去。
-
optional类的改进
-
ifPresentOrElse(Consumer,Runnable)可以同时处理为空和不为空的两个情况了,如果不为空执行Consumer,否则执行runnable
public static void main(String[] args) { method("字符串"); method(null); } public static void method(String str) { Optional .ofNullable(str) .ifPresentOrElse(s-> System.out.println(s),()-> System.out.println("传入参数为空")); }
-
or(Supplier)如果为空,就用一个option替换掉这个optional
public static void main(String[] args) { method("字符串"); method(null); } public static void method(String str) { Optional .ofNullable(str) .or(()->Optional.ofNullable("替换的包装")) .ifPresent(s-> System.out.println(s)); }
-
-
泛型的改进
我们定义了如下抽象类
public abstract class Test<T> { private T t; public Test(T t){ this.t = t; } public void method(){ System.out.println(t); } }
在java9之前的版本中,无法自动识别传入的参数的类型并报错,但是java9中java会自动推断类型不会报错
public class Main { public static void main(String[] args) { Test<String> test = new Test<>("aaa") {}; test.method(); } }
还有一些其他的不常用改进,感兴趣的可以再自行查阅
三、java 10 新特性
-
局部变量类型推断
var类型推断,使用var在定义变量时替代变量类型,只能用于在定义时初始化的变量且仅适用于局部变量
public class Main { public static void main(String[] args) { var a = "aaa"; System.out.println(a.toUpperCase()); } }
还有一些其他的不常用改进,感兴趣的可以再自行查阅
四、Java 11 新特性
-
用于Lambda的形参局部变量语法
public class Main { public static void main(String[] args) { Consumer<String> consumer = (var str) -> { System.out.println(str); }; consumer.accept("形参"); } }
-
针对String 的方法改进
-
判断字符串中是否全部为空格 isBlank()方法
-
将字符串重复拼接n次并返回 repeat(n)方法
-
根据换行符判断字符串分为几部分 .lines().count() .lines()方法会将字符串根据换行符分段为流,conut()可以计数
-
去除首尾空格,strip() 是trim()的增强版,trim()无法去除unicode空白字符,而strip可以
-
五、Java 12-16 新特性
-
新switch语法(14正式开放) switch可以有返回值并且写法更简洁,但这种写法必须要包含所有返回值,否则报错,因此要写default
public class Main { public static void main(String[] args) { System.out.println(grade(77)); } public static String grade(int score){ score /= 10; return switch (score){ case 10,9 -> "优秀"; case 8,7 -> "良好"; case 6 -> "及格"; default -> "不及格"; }; } }
如果我们最后在case中还要进行一些操作再进行返回,要使用yield关键字
public class Main { public static void main(String[] args) { System.out.println(grade(95)); } public static String grade(int score){ score /= 10; return switch (score){ case 10,9 -> { System.out.println("点名表扬"); yield "优秀"; } case 8,7 -> "良好"; case 6 -> "及格"; default -> { System.out.println("打电话叫家长"); yield "不及格"; } }; } }
-
三引号(15正式开放) 字符串在编写时不需要对特殊字符进行转义,而是全部认为是字符,但是不能连续出现三个"
public class Main { public static void main(String[] args) { String str = "111"; String a = """ dasd <a href = str.length '' ' """; System.out.println(a); } }
-
空指针改进:可以更明确的指出空指针的异常原因。比如再类型转换时如果为空,会明确告诉你由于传入的参数为空因此无法类型转换,而在改进之前只会告诉你空指针异常,原因需要你自己找寻。
-
记录类型(Record),参数会自动实现set、get、hashcode等方法(java16开放)
写一个学生类
public record Student(String id, String name,int age) { } 调用自动实现的方法 public class Main { public static void main(String[] args) { Student student = new Student("123","张三",19); System.out.println(student.age()); System.out.println(student.toString()); System.out.println(student); } }
六、java 17 新特性
-
密封类型 sealed 关键字修饰类,仅让被允许的子类继承
我们让A被修饰,让B去继承A
public sealed class A permits B { } public final class B extends A { }
-
密封类型可以基于普通类、抽象类、接口,也可以是继承自其他抽象类的子类或者是实现其他接口的类等。
-
必须有子类,且不能是匿名内部类
-
sealed不能与final、non-sealed同时出现
-
继承的子类必须为final、sealed或是non-sealed的
-
学习参考: 青空の霞光的个人空间-青空の霞光个人主页-哔哩哔哩视频
java新手,欢迎大家学习、交流和批评指正。