1996 JDK1.0
2004 JDK5.0 里程碑式的版本
2014 JDK8.0 --->LTS
2017.9 JDK9.0
2018.9 JDK11 --->LTS
2021.9 JDK17 --->LTS
学习新特性 角度1:新的语法规则
自动装箱、自动拆箱、注解、enum、Lamda表达式、方法引用、switch表达式、try-catch变化、record等
角度2:增加、过时。删除api
StringBuilder、ArrayList、新的日期时间API、Optional等
角度3:JVM参数的调整、SC的变化、内存结构
JDK8新特性:
1、Lamda表达式
@Test
public void test2(){
//常规写法:重写Comparator接口的compare方法,调用run方法
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(01,02);
}
};
int compare1 = com1.compare(18,1024);
System.out.println(compare1);
System.out.println("--------------");
//lambda表达式的写法
//保留等号前的定义,已经确定的类型(如Integer)删去不写,保留形参,指向方法体内容(大括号也可删去)
Comparator<Integer> com2 = ( o1, o2) -> Integer.compare(01,02);
int compare2 = com2.compare(18, 1024);
System.out.println(compare2);
}
(1)Lambda表达式的使用举例:
( o1, o2) -> Integer.compare(01,02);
(2)lambda操作符:
->
Lambda形参列表(重写后的抽象方法中的形参列表) -> lambda体(重写后的方法体)
(3)lambda表达式的本质:
一方面,lambda表达式作为接口的实现类的对象--->万事万物皆对象
另一方面,lambda表达式是一个匿名函数
(4)函数式接口
如果接口中只有一个抽象方法,则此接口称为函数式接口
只有给函数式接口提供实现类对象时,我们才能使用lambda表达式。
(5)API中函数式接口所在的包
jdk8中声明的函数式接口都在java.util.function包下。
(6)常见的函数接口
消费型接口:Consumer<T> void accept(T t)
供给型接口:Supplier<T> T get()
函数型接口:Function<T,R> R apply(T t)
判断型接口:Predicate<T> boolean test(T t)
(7)lambda
语法格式一:无参,无返回值
无参则保留小括号,无返回值则重写输出语句
Runnable r2 = () -> {
System.out.println("……又在仗着我会对你心软,说一些骗我的思念吗。");
};
语法格式二:Lambda 需要一个参数,但是没有返回值。
Consumer<String> con2 = (String str)-> System.out.println(str);
语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
Comparator<Integer> com2 = ( o1, o2) -> Integer.compare(01,02);
语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
Consumer<String> CON2 = s -> {System.out.println(s);};
语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
Comparator<Integer> com4 = ( o1, o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com4.compare(18,1024));
语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
Consumer<String> con2 = (String str)-> System.out.println(str);
方法引用:
1、举例:
Interger :: compare
2、说明:
可以使用方法引用的前提:必须能够使用lambda表达式
当需要提供一个函数式接口的实例时,我们可以使用lambda表达式提供此实例。
3、方法引用的本质:
方法引用作为了函数接口的实现 --->万事万物皆对象
4、格式
类(或对象) :: 方法名
5、具体情况
情况1 对象::实例方法
原形式:
Person per1 = new Person("Qum");
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return per1.getName();
}
};
System.out.println(supplier.get());
方法引用;
//方法引用 格式 对象::方法
Supplier<String> supplier2 = per3::getName;
System.out.println(supplier2.get());
函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b 形参列表和返回值类型都相同时,此时可以考虑使用方法b对方法a进行替换
注意,此方法b非静态,需要对象调用
情况2 类::静态方法
函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b 形参列表和返回值类型都相同时,此时可以考虑使用方法b对方法a进行替换
此方法b为静态方法,不需对象调用。
@Test
public void test4(){
Function<Double,Long> fun1 = new Function<Double, Long>() {
@Override
public Long apply(Double aDouble) {
return Math.round(aDouble);
}
};
Function<Double,Long> fun2 = Math::round;//因为没有对象存在,静态方法由类发起,写作Math::round
}
情况3 类::实例方法
函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b 返回值类型都相同,且,抽象方法a中有n个参数,且抽象方法a的第一个参数为方法b的调用者,抽象方法a的后n-1个参数与方法b的n-1个参数相同:
此时可以考虑使用方法b对方法a进行替换
@Test
//类::实例方法
public void test5(){
Comparator<String> com1 = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
System.out.println(com1.compare("Dit","Qum"));
//引用方法
Comparator<String>comparator = String::compareTo;
}
构造器引用
1、格式:
Supplier<Employee> sup1 = Employee::new;
System.out.println(sup2.get());
2、说明
调用了类名对应的类中的某个确定的构造器。
具体调用的是哪一个构造器取决于函数式接口的抽象方法的形参列表。
数组引用
1、格式:
数组名[] ::new