哪里有网站建设商家2345浏览器网址导航
Java 8新特性简介
总结:
1.截止目前,JDK比较重要的时间节点和版本说明 1996 JDK1.0 2004 JDK5.0 最重要的一个里程碑式的版本 2014 JDK8.0 排第二的里程碑式的版本---> LTS 2017.9 JDK9.0 从此版本开始,每半年发布一个新的版本 2018.9 JDK11 ----> LTS 2021.9 JDK17 ----> LTS2.如何学习新特性? > 角度1:新的语法规则(多关注) 自动装箱、自动拆箱、注解、enum、Lambda表达式、方法引用、switch表达式、try-catch变化、record等 > 角度2:增加、过时、删除API StringBuilder、ArrayList、新的日期时间的API、Optional等 > 角度3:底层的优化、JVM参数的调整、GC的变化、内存结构(永久代--->元空间)
Lambda 表达式
总结:
1.Lambda表达式的使用举例: (o1,o2)->Integer.compare(o1,o2); 2.Lambda表达式的格式举例:3.Lambda表达式的格式: -> : lambda操作符或箭头操作符 -> 的左边: lambda形参列表,对应着要重写的接口中的抽象方法的形参列表。 -> 的右边: lambda体,对应着接口的实现类要重写的方法的方法体。 4.Lambda表达式的本质: > 一方面,lambda表达式作为接口的实现类的对象。 ----> "万事万物皆对象 > 另一方面,lambda表达式是一个匿名函数。 5.函数式接口: 5.1 什么是函数式接口?为什么需要函数式接口? > 如果接口中只声明有一个抽象方法,则此接口就称为函数式接口。 > 因为只有给函数式接口提供实现类的对象时,我们才可以使用lambda表达式。 5.2 api中函数式接口所在的包 jdk8中声明的函数式接口都在java.util.function包下 5.3 4个基本的函数式接口接口 对应的抽象方法 消费型接口:Consumer<T> void accept(T t) 供给型接口:Supplier<T> T get() 函数型接口:Function<T,R> R apply(T t) 判断型接口:Predicate<T> boolean test(T t)6.Lambda表达式的语法规则总结 -> 的左边:lambda形参列表,参数的类型都可以省略。如果形参只有一个,则一对()也可以省略。 -> 的右边:lambda体,对应着重写的方法的方法体。如果方法体中只有一行执行语向,则一对{}可以省略。如果有return关键字,则必须一并省略。
代码:
public class LambdaTest {@Testpublic void test1(){Runnable r1 = new Runnable(){@Overridepublic void run() {System.out.println("我爱北京天安门");}};r1.run();System.out.println("*******************");//Lambda表达式的写法:Runnable r2 = () -> {System.out.println("我爱上海东方明珠");};r2.run();}@Testpublic void test2(){Comparator<Integer> com1 = new Comparator<Integer>(){@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1,o2);}};int compare1 = com1.compare(12,21);System.out.println(compare1); //-1System.out.println("*************************");//Lambda表达式的写法Comparator<Integer> com2 = (Integer o1, Integer o2)->Integer.compare(o1,o2);int compare2 = com2.compare(23,21);System.out.println(compare2); //1System.out.println("*****************");//方法引用Comparator<Integer> com3 = Integer :: compare;int compare3 = com3.compare(23,21);System.out.println(compare3); //1}
}
代码2:
public class LambdaTest1 {//语法格式一:无参,无返回值@Testpublic void test1() {Runnable r1 = new Runnable() {public void run() {System.out.println("我爱北京天安门");}};r1.run();System.out.println("*****************");Runnable r2 = () -> {System.out.println("我爱北京天安门");};r2.run();}//语法格式二:Lambda需要一个参数,但是没有返回值@Testpublic void test2() {Consumer<String> con = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};con.accept("谎言和誓言的区别是什么?");System.out.println("***************");Consumer<String> con1 = (String s) -> {System.out.println(s);};con1.accept("一个是说的人当真了,一个是听的人当真了");}//语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”@Testpublic void test3() {Consumer<String> con1 = (String s) -> {System.out.println(s);};con1.accept("如果大学可以重来,你最想重来的事是啥?");System.out.println("********************");Consumer<String> con2 = (s) -> {System.out.println(s);};con1.accept("谈一场轰轰烈烈的爱情");}@Testpublic void test3_1() {int[] arr = {1, 2, 3, 4, 5}; //类型推断HashMap<String, Integer> map = new HashMap<>(); //类型推断var entrySet = map.entrySet();//类型推断,在jdk10及之后可以用}//语法格式四:Lambda若只需要一个参数时,参数的小括号可以省略@Testpublic void test4() {Consumer<String> con1 = (s) -> {System.out.println(s);};con1.accept("世界那么大,我想去看看");System.out.println("****************");Consumer<String> con2 = s -> {System.out.println(s);};con1.accept("世界那么大,我想去看看");}//语法格式五:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值@Testpublic void test5() {Comparator<Integer> com1 = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);}};System.out.println(com1.compare(12, 21));System.out.println("**********************");Comparator<Integer> com2 = (o1, o2) -> {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);};System.out.println(com1.compare(12, 21));}//语法格式六:当Lambda体只有一条语句时,return与大括号若有,都可以省略@Testpublic void test6(){Comparator<Integer> com1 = (o1,o2)->{return o1.compareTo(o2);};System.out.println(com1.compare(12, 21));System.out.println("**************");Comparator<Integer> com2 = (o1,o2)-> o1.compareTo(o2);}
}
function文件:
public class MyFunctionalInterfaceTest {@Testpublic void test1(){MyFunctionalInterface m = () -> System.out.println("hello");m.method();}
}@FunctionalInterface
public interface MyFunctionalInterface {void method();
// void method1();
}
函数式接口
方法引用与构造器引用
方法引用总结:
1.举例: Integer :: compare; 2.方法引用的理解 > 方法引用,可以看做是基于lambda表达式的进一步刻画。 > 当需要提供一个函数式接口的实例时,我们可以使用lambda表达式提供此实例。> 当满足一定的条件的情况下,我们还可以使用方法引用或构造器引用替换lambda表达式。 3.方法引用的本质: 方法引用作为了函数式接口的实例。 ---> "万事万物皆对象" 4.格式: 类(或对象)::方法名 5.具体使用情况说明 情况1:对象::实例方法 要求:函数式接口中的抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值类型都相同。 此时,可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。 注意:此方法b是非静态的方法,需要对象调用。 情况2:类::静态方法 要求:函数式接口中的抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值类型都相同(或一致)。 此时,可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。 注意:此方法b是静态的方法,需要类调用。 情况3:类 ::实例方法 要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的返回值类型相同。同时,抽象方法a中有n个参数,方法b中有n-1个参数,且抽象方法a的第1个参数作为方法b的调用者,且抽象方法a的后n-1个参数与方法b的n-1个参数的类型相同(或一致)。则可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。 注意:此方法b是非静态的方法,需要对象调用。但是形式上,写出对象a所属的类
构造器数组引用总结:
1.构造器引用 1.1 格式: 类名 :: new 1.2 说明: > 调用了类名对应的类中的某一个确定的构造器 > 具体调用的是类中的哪一个构造器呢?取决于函数式接口的抽象方法的形参列表! 2.数组引用 格式: 格式:数组名[]::new
代码:
data文件
Employee
public class Employee {int id;String name;int age;double salary;public Employee() {}public Employee(int id) {this.id = id;}public Employee(int id, String name) {this.id = id;this.name = name;}public Employee(int id, String name, int age, double salary) {this.id = id;this.name = name;this.age = age;this.salary = salary;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", salary=" + salary +'}';}// @Override
// public boolean equals(Object o) {
// if (o == null || getClass() != o.getClass()) return false;
// Employee employee = (Employee) o;
// return id == employee.id && age == employee.age && Double.compare(salary, employee.salary) == 0 && Objects.equals(name, employee.name);
// }
//
// @Override
// public int hashCode() {
// return Objects.hash(id, name, age, salary);
// }@Overridepublic boolean equals(Object o) {if(this == o)return true;if(o==null||getClass()!=o.getClass())return false;Employee employee = (Employee)o;if(id!=employee.id)return false;if(age!=employee.age)return false;if(Double.compare(employee.salary,salary)!=0)return false;return name != null ? name.equals(employee.name) : employee.name == null;}@Overridepublic int hashCode() {int result;long temp;result = id;result = 31*result+(name!=null?name.hashCode():0);result = 31*result+age;temp = Double.doubleToLongBits(salary);result = 31*result+(int)(temp^(temp>>>32));return result;}
}
EmployeeDate
public class EmployeeDate {public static List<Employee> getEmployees() {List<Employee> list = new ArrayList<>();list.add(new Employee(1001, "马化腾", 34, 6000.38));list.add(new Employee(1002, "马云", 2, 19876.12));list.add(new Employee(1003, "刘强东", 33, 3000.82));list.add(new Employee(1004, "雷军", 26, 7657.37));list.add(new Employee(1005, "李彦宏", 65, 5555.32));list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));list.add(new Employee(1007, "任正非", 26, 4333.32));list.add(new Employee(1008, "扎克伯格", 35, 2500.32));return list;}
}
方法引用代码:
public class MethodRefTest {//情况一:类(或对象)::方法名//Consumer中的void accept(T t)//PrintStream中的void println(T t)@Testpublic void test1() {//1.Consumer<String> con1 = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};con1.accept("hello!");//2.lambda表达式Consumer<String> con2 = s -> System.out.println(s);con2.accept("hello!");//3.方法引用PrintStream ps = System.out;Consumer<String> con3 = ps::println;con3.accept("hello!");}//Supplier中的T get()//Employee中的String getName()@Testpublic void test2() {Employee emp = new Employee(1001, "马化腾", 34, 6000.38);//1.Supplier<String> sup1 = new Supplier<String>() {@Overridepublic String get() {return emp.getName();}};System.out.println(sup1.get());//2.lambda表达式Supplier<String> sup2 = () -> emp.getName();System.out.println(sup2.get());//3.方法引用Supplier<String> sup3 = emp::getName;System.out.println(sup3.get());}//情况二:类 :: 静态方法//Comparator中的int compare(T t1,T t2)//Integer中的int compare(T t1,T t2)@Testpublic void test3() {//1.Comparator<Integer> com1 = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1, o2);}};System.out.println(com1.compare(12, 21));//2.Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1, o2);System.out.println(com2.compare(21, 34));//3.方法引用Comparator<Integer> com3 = Integer::compare;System.out.println(com3.compare(34, 34));}//Function中的R apply(T t)//Math中的Lang round(Double d)@Testpublic void test4() {//1.Function<Double, Long> fun1 = new Function<Double, Long>() {@Overridepublic Long apply(Double aDouble) {return Math.round(aDouble);}};//2.Function<Double, Long> fun2 = aDouble -> Math.round(aDouble);//3.方法引用Function<Double, Long> fun3 = Math::round;}//情况三:类 ::实例方法(难)//Comparator中的int compare(T t1,T t2)//String中的int t1.compareTo(t2)@Testpublic void test5() {//1.Comparator<String> com1 = new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}};System.out.println(com1.compare("abc", "abb"));//2.Comparator<String> com2 = (s1, s2) -> s1.compareTo(s2);System.out.println(com2.compare("abc", "abb"));//3.Comparator<String> com3 = String::compareTo;System.out.println(com3.compare("abc", "abb"));}//BiPredicate中的boolean test(T t1,T t2)//String中的boolean t1.equals(t2)@Testpublic void test6() {BiPredicate<String,String> biPre1 = new BiPredicate<String, String>() {@Overridepublic boolean test(String s1,String s2){return s1.equals(s2);}};//2.BiPredicate<String,String> biPre2 = (s1,s2) -> s1.equals(s2);//3.方法引用BiPredicate<String,String> biPre3 = String :: equals;}//Function中的R apply(T t)//Employee中的String getName()@Testpublic void test7(){Employee emp = new Employee(1001, "马化腾", 34, 6000.38);//1Function<Employee,String> fun1 = new Function<Employee,String>(){@Overridepublic String apply(Employee employee) {return employee.getName();}};System.out.println(fun1.apply(emp));//2.Function<Employee,String> fun2 = employee -> employee.getName();System.out.println(fun2.apply(emp));//3.方法引用Function<Employee,String> fun3 = Employee :: getName;System.out.println(fun3.apply(emp));}
}
构造器引用代码:
public class ConstructorRefTest {//构造器引用//Supplier中的T get()@Testpublic void test1(){//1.Supplier<Employee> sup1 = new Supplier<Employee>(){@Overridepublic Employee get() {return new Employee();}};System.out.println(sup1.get());//2.方法引用Supplier<Employee> sup2 = Employee :: new; //调用的是Employee类中空参的构造器System.out.println(sup2.get());}//Function中的R apply(T t)@Testpublic void test2(){//1.Function<Integer,Employee> func1 = new Function<Integer,Employee>() {@Overridepublic Employee apply(Integer id) {return new Employee(id);}};System.out.println(func1.apply(12));//2.构造器引用Function<Integer, Employee> func2 = Employee::new; //调用的是Employee类中参数是Integer/int类型的构造器System.out.println(func2.apply(11));}//BiFunction中的R apply(T t,U u)@Testpublic void test3(){//1.BiFunction<Integer,String,Employee> func1 = new BiFunction<Integer, String, Employee>() {@Overridepublic Employee apply(Integer id, String name) {return new Employee(id,name);}};System.out.println(func1.apply(10, "Tom"));//2.BiFunction<Integer, String, Employee> func2 = Employee::new; //调用的是Employee类中参数是Integer/int、String类型的构造器System.out.println(func2.apply(11, "Tony"));}//数组引用//Function中的R apply(T t)@Testpublic void test4(){//1.Function<Integer,Employee[]> func1 = new Function<Integer,Employee[]>(){@Overridepublic Employee[] apply(Integer length) {return new Employee[length];}};System.out.println(func1.apply(10).length);//2.Function<Integer,Employee[]> func2 = Employee[]::new;System.out.println(func2.apply(11).length);}
}
强大的Stream API
强大的Stream API: Collectors
总结:
1.Stream API vs 集合框架 > Stream API 关注的是多个数据的计算(排序、查找、过滤、映射、遍历等),面向CPU的。集合关注的数据的存储,向下内存的。 > Stream API 之于集合,类似于SQL之于数据表的查询。 2.使用说明 ① stream 自己不会存储元素。 ② stream 不会改变源对象。相反,他们会返回一个持有结果的新stream。 ③ stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。即一旦执行终止操作,就执行中间操作链,并产生结果 ④ Stream一旦执行了终止操作,就不能再调用其它中间操作或终止操作了。 3.Stream 执行流程 步骤1:Stream的实例化 步骤2:一系列的中间操作 步骤3:执行终止操作
代码:
StreamAPITest
public class StreamAPITest {//创建Stream方式一:通过集合@Testpublic void test1(){List<Employee> list = EmployeeDate.getEmployees();//default Stream<E> stream():返回一个顺序流Stream<Employee> stream = list.stream();//default Stream<E> parallelStream(): 返回一个并行流Stream<Employee> stream1 = list.parallelStream();System.out.println(stream);System.out.println(stream1);}//创建Stream方式二:通过数组@Testpublic void test2(){//调用Arrays类的static <T> Stream<T> stream(T[] array):返回一个流Integer[] arr = new Integer[]{1,2,3,4,5};Stream<Integer> stream = Arrays.stream(arr);int[] arr1 = new int[]{1,2,3,4,5};IntStream stream1 = Arrays.stream(arr1);}//创建Stream方式三:通过Stream的of()@Testpublic void test3(){Stream<String> stream = Stream.of("AA", "BB", "CC", "SS", "DD");System.out.println(stream);}
}
代码2:
public class StreamAPITest1 {//1-筛选与切片@Testpublic void test1(){//filter(Predicate p)——接受Lambda,从流中排除某些元素//练习:查询员工表中薪资大于7000的员工信息List<Employee> list = EmployeeDate.getEmployees();Stream<Employee> stream = list.stream();stream.filter(emp -> emp.getSalary() > 7000).forEach(System.out::println);System.out.println();//limit(n)——截断流,使其元素不超过给定数量//错误的,因为Stream已经执行了终止操作,就不可以再调用其他的中间操作或终止操作了
// stream.limit(2).forEach(System.out::println);list.stream().limit(4).forEach(System.out::println);System.out.println();//获取薪资大于7000的前两个list.stream().filter(emp->emp.getSalary()>7000).limit(2).forEach(System.out::println);System.out.println();//skip(n) —— 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limitlist.stream().skip(5).forEach(System.out::println);System.out.println();//distinct()——筛选,通过流所生成元素的hashCode()和equals()去除重复元素list.add(new Employee(1009, "马斯克", 40, 12500.32));list.add(new Employee(1009, "马斯克", 40, 12500.32));list.add(new Employee(1009, "马斯克", 40, 12500.32));list.add(new Employee(1009, "马斯克", 40, 12500.32));list.stream().distinct().forEach(System.out::println);}//映射@Testpublic void test2(){//map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上//练习:转换成大写List<String> list = Arrays.asList("aa","bb","cc","dd");//方式1:list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);//方式2:list.stream().map(String :: toUpperCase).forEach(System.out::println);//练习:获取员工姓名长度大于3的员工List<Employee> employees = EmployeeDate.getEmployees();employees.stream().filter(emp->emp.getName().length()>3).forEach(System.out::println);//练习:获取员工姓名长度大于3的员工姓名//方式1:employees.stream().filter(emp -> emp.getName().length() > 3).map(emp -> emp.getName()).forEach(System.out::println);//方式2:employees.stream().map(emp -> emp.getName()).filter(name -> name.length() > 3).forEach(System.out::println);//方式3:employees.stream().map(Employee::getName).filter(name->name.length()>3).forEach(System.out::println);}//3-排序@Testpublic void test3(){//sorted()——自然排序Integer[] arr = new Integer[]{345,3,64,3,46,7,3,34,65,68};String[] arr1 = new String[]{"GG", "DD", "MM", "SS", "JJ"};Arrays.stream(arr).sorted().forEach(System.out::println);System.out.println(Arrays.toString(arr)); //arr数组并没有因为升序,被调整Arrays.stream(arr1).sorted().forEach(System.out::println);//因为Employee没有实现Comparable接口,所以报错!
// List<Employee> list = EmployeeDate.getEmployees();
// list.stream().sorted().forEach(System.out::println);//sorted(Comparator com)——定制排序List<Employee> list = EmployeeDate.getEmployees();list.stream().sorted((e1, e2) -> e1.getAge() - e2.getAge()).forEach(System.out::println);//针对于字符串从大到小排序Arrays.stream(arr1).sorted((s1, s2) -> s1.compareTo(s2)).forEach(System.out::println);Arrays.stream(arr1).sorted(String::compareTo).forEach(System.out::println);}
}
代码3:
public class StreamAPITest2 {//1-匹配与查找@Testpublic void test1(){//allMatch(Predicate p)——检查是否匹配所有元素//练习:是否所有的员工的年龄都大于18List<Employee> list = EmployeeDate.getEmployees();System.out.println(list.stream().allMatch(emp -> emp.getAge() > 18)); //false//anyMatch(Predicate p)——检查是否至少匹配一个元素//练习:是否存在年龄大于18岁的员工System.out.println(list.stream().anyMatch(emp->emp.getAge()>18));//练习:是否存在员工的工资大于10000System.out.println(list.stream().anyMatch(emp -> emp.getSalary() > 10000));//findFirst——返回第一个元素System.out.println(list.stream().findFirst().get());}@Testpublic void test2(){//count——返回流中元素的总个数List<Employee> list = EmployeeDate.getEmployees();System.out.println(list.stream().count());System.out.println(list.stream().filter(emp->emp.getSalary()>7000).count());//max(Comparator c)———返回流中最大值//练习:返回最高工资的员工System.out.println(list.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));//练习:返回最高的工资//方式1:System.out.println(list.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).get().getSalary());//方式2:System.out.println(list.stream().map(emp -> emp.getSalary()).max((salary1, salary2) -> Double.compare(salary1, salary2)).get());System.out.println(list.stream().map(emp->emp.getSalary()).max(Double::compare).get());//min(Comparator c)——返回流中最小值//练习:返回最低工资的员工System.out.println(list.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));//forEach(Consumer c)——内部迭代list.stream().forEach(System.out::println);//针对于集合,jdk8中增加了一个遍历的方法list.forEach(System.out::println);//针对于List来说,遍历的方式:①使用Iterator ②增强for ③一般for ④forEach()}//2-归约@Testpublic void test3(){//reduce(T identity, BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回 T//练习1:计算1-10的自然数的和List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);System.out.println(list.stream().reduce(0, (x1, x2) -> x1 + x2));System.out.println(list.stream().reduce(0, (x1, x2) -> Integer.sum(x1, x2)));System.out.println(list.stream().reduce(0, Integer::sum));System.out.println(list.stream().reduce(10,(x1,x2)->x1+x2));//reduce(BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回 Optional<T>// 练习2:计算公司所有员工工资的总和List<Employee> employeeList = EmployeeDate.getEmployees();employeeList.stream().map(emp -> emp.getSalary()).reduce((salary1, salary2) -> Double.sum(salary1, salary2));employeeList.stream().map(emp -> emp.getSalary()).reduce(Double::sum);}//3-收集@Testpublic void test4(){List<Employee> list = EmployeeDate.getEmployees();//collect(Collector c)——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法//练习1:查找工资大于6000的员工,结果返回为一个List或SetList<Employee> list1 = list.stream().filter(emp -> emp.getSalary() > 6000).collect(Collectors.toList());list1.forEach(System.out::println);//固定到了list当中,可以根据list做一些其他操作System.out.println();list.forEach(System.out::println);System.out.println();//练习2:按照员工的年龄进行排序,返回到一个新的List中List<Employee> list2 = list.stream().sorted((e1, e2) -> e1.getAge() - e2.getAge()).collect(Collectors.toList());list2.forEach(System.out::println);}
}
Optional 类
总结:
JDK8的新特性,JDK9-11中新增了一些方法。 1.为什么需要0ptional类? 为了避免代码中出现空指针异常。 2.如何实例化? static <T> Optional<T> ofNullable(T value):用来创建一个Optional实例,value可能是空,也可能非空 3.常用方法
代码 :
public class OptionalTest {@Testpublic void test(){String star = "迪丽热巴";star = null;//使用Optional避免空指针的问题//1.实例化://ofNullable(T value):用来创建一个Optional实例,value可能是空,也可能非空Optional<String> optional = Optional.ofNullable(star);//orElse(t other):如果Optional实例内部的value属性不为null,则返回value,如果value为null//则返回otherString otherStar = "杨幂";String finalStar = optional.orElse(otherStar);System.out.println(finalStar.toString());}@Testpublic void test2(){String star = "迪丽热巴";
// star = null;Optional<String> optional = Optional.ofNullable(star);//get():取出内部的value值System.out.println(optional.get());}
}
JDK 9 的发布
一、JDK 和 JRE 目录结构的改变
二、模块化系统: Jigsaw ——>Modularity
三、Java的REPL工具: jShell命令
四、语法改进:接口的私有方法
六、语法改进:try语句
七、String存储结构变更
八、集合工厂方法:快速创建只读集合
九、InputStream 加强
十、增强的 Stream API
十一、Optional获取Stream的方法
十二、Javascript引擎升级:Nashorn
Java 10 新特性
JDK10的12个JEP
一、局部变量类型推断
二、集合新增创建不可变集合的方法
Java 11 新特性
一、新增了一系列字符串处理方法
二、Optional 加强
三、局部变量类型推断升级
四、全新的HTTP 客户端API
五、更简化的编译运行程序
六、废弃Nashorn引擎
七、ZGC
八、其它新特性
总结及代码
jshell:
这是JDK9的新特性 1.命令行中通过指令jshell,调取jshell工具 2.常用指令: /help:获取关使用 jshell 工具的信息 /help intro : jshell 工具的简介 /list :列出当前 session 里所有有效的代码片段 /vars :查看当前 session 下所有创建过的变量 /methods :查看当前 session 下所有创建过的方法 /imports :列出导入的包 /history :键入的内容的历史记录 /edit :使用外部代码编辑器来编写 Java 代码 /exit :退出 jshell 工具
try-catch:
public class TryCatchTest {/*** 举例1:* JDK7之前的写法*/@Testpublic void test01() {FileWriter fw = null;BufferedWriter bw = null;try {fw = new FileWriter("test.txt");bw = new BufferedWriter(fw);bw.write("hello,世界");} catch (IOException e) {e.printStackTrace();} finally {try {if (bw != null)bw.close();} catch (IOException e) {e.printStackTrace();}try {if (fw != null)fw.close();} catch (IOException e) {e.printStackTrace();}}}/*** 举例1:* JDK7中的写法*/@Testpublic void test02() {try (FileWriter fw = new FileWriter("test.txt");BufferedWriter bw = new BufferedWriter(fw)) {bw.write("hello,世界");} catch (IOException e) {e.printStackTrace();}}/*** 举例2:从test.txt(utf-8)文件中,读取内容,写出到abc.txt(gbk)文件中* JDK7之前的写法*/@Testpublic void test03() {BufferedReader br = null;BufferedWriter bw = null;try {FileInputStream fis = new FileInputStream("test.txt");InputStreamReader isr = new InputStreamReader(fis, "utf-8");br = new BufferedReader(isr);FileOutputStream fos = new FileOutputStream("abc.txt");OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");bw = new BufferedWriter(osw);String str;while ((str = br.readLine()) != null) {bw.write(str);bw.newLine();bw.flush();}} catch (IOException e) {e.printStackTrace();} finally {try {bw.close();} catch (IOException e) {e.printStackTrace();}try {br.close();} catch (IOException e) {e.printStackTrace();}}}/*** 举例2:从test.txt(utf-8)文件中,读取内容,写出到abc.txt(gbk)文件中* JDK7中的写法*/@Testpublic void test04() {try (FileInputStream fis = new FileInputStream("test.txt");InputStreamReader isr = new InputStreamReader(fis, "utf-8");BufferedReader br = new BufferedReader(isr);FileOutputStream fos = new FileOutputStream("abc.txt");OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");BufferedWriter bw = new BufferedWriter(osw);) {String str;while ((str = br.readLine()) != null) {bw.write(str);bw.newLine();bw.flush();}} catch (IOException e) {e.printStackTrace();}}//jdk9中举例:@Testpublic void test05(){InputStreamReader reader = new InputStreamReader(System.in);OutputStreamWriter writer = new OutputStreamWriter(System.out);try(reader;writer){//reader、writer是final的,不可再被赋值}catch(IOException e){e.printStackTrace();}}
}
局部变量类型推断
这是JDK10的新特性。
public class VarTest {//可以使用的场景@Testpublic void test01(){//1.局部变量的实例化var list = new ArrayList<String>();var set = new LinkedHashSet<Integer>();//2.增强for循环中的索引for(var v:list){System.out.println(v);}//3.传统for循环中for(var i = 0;i<100;i++){System.out.println(i);}//4.返回值类型含复杂泛型结构var iterator = set.iterator();HashMap<String,Integer> map = new HashMap<>();var entrySet = new HashMap<>();
// Iterator<Map.Entry<Integer, Student>> iterator = set.iterator();}/*** 声明一个成员变量* 声明一个数组变量,并为数组静态初始化(省略new的情况下)* 方法的返回值类型* 方法的参数类型* 没有初始化的方法内的局部变量声明* 作为catch块中异常类型* Lambda表达式中函数式接口的类型* 方法引用中函数式接口的类型*///声明一个成员变量
// var i;
// var j = 0;@Testpublic void test2(){// 声明一个数组变量,并为数组静态初始化(省略new的情况下)var arr = new int[]{1,2,3,4,5};
// var arr = {1,2,3,4,5};}//没有初始化的方法内的局部变量声明//方法的参数类型//方法的返回值类型
// public var method(int i,var m){
// var i = 0;
// }@Testpublic void test3(){
// try{
// System.out.println(10/0);
// }catch(var e){ //作为catch块中异常类型
// e.printStackTrace();
// }//方法引用中函数式接口的类型
// var com = (s1,s2)->s1.compareTo(s2); //Lambda表达式中函数式接口的类型}
}
instanceof模型匹配
JDK14中预览特性。 JDK15中第二次预览。 JDK16中转正特性。 JDK14之前: // 先判断类型 if(obj instanceof string){// 然后转换String s=(string)obj;// 然后才能使用 } JDK14:(自动匹配模式) if(obj instanceof string s){//如果类型匹配 直接使用 }else {//如果类型不匹配则不能直接使用 }
public class InstanceOfTest {/*** 举例1:* JDK14之前*/@Testpublic void test1(){Object obj = new String("hello,Java14");if(obj instanceof String){String str = (String)obj;System.out.println(str.contains("Java"));}else{System.out.println("非String类型");}}/*** 举例1:* JDK14中*/@Testpublic void test2(){Object obj = new String("hello,Java14");if(obj instanceof String str){System.out.println(str.contains("Java"));}else{System.out.println("非String类型");}}
}
/*** 举例2:*/
class Computer{private String model; //型号private double price;//价格//方式1:
// public boolean equals(Object o){
// if(o instanceof Computer) {
// Computer other = (Computer)o;
// if(this.model.equals(other.model)&&this.price==other.price){
// return true;
// }
// }
// return false;
// }//方式2:
// public boolean equals(Object o){
// if(o instanceof Computer other){
// return this.model.equals(other.model)&&this.price==other.price;
// }
// return false;
// }public boolean equals(Object o) {return o instanceof Computer other && this.model.equals(other.model) && this.price == other.price;}
}
switch表达式
JDK12中预览特性:switch表达式 JDK13中二次预览特性:switch表达式 JDK14中转正特性:switch表达式JDK17的预览特性:switch的模式匹配
public class SwitchPatternTest {public static void main(String[] args){System.out.println(formatter(12));System.out.println(formatterSwitchPattern(12));}/*** JDK17之前*/static String formatter(Object o){String formatted = "unknown";if(o instanceof Integer i){formatted = "int" + i;}else if(o instanceof Long l){formatted = "long" + l;}else if(o instanceof Double d){formatted = "double" + d;}else if(o instanceof String s){formatted = "String" + s;}return formatted;}/*** JDK17中switch的模式匹配*/static String formatterSwitchPattern(Object o){String formatted = switch(o){case Integer i:yield "int" + i;case Long l:yield "long" + l;case Double d:yield "double" + d;case String s:yield "String" + s;default:yield o.toString();};return formatted;}
}
enum Week{MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}
public class SwitchExceptionTest {/*** 举例1:* JDK12之前的写法*/@Testpublic void test1(){Week day = Week.FRIDAY;int num=0;switch(day){case MONDAY:num = 20;System.out.println(1);break;case TUESDAY:case WEDNESDAY:case THURSDAY:num = 20;System.out.println(2);break;case FRIDAY:System.out.println(3);break;case SATURDAY:case SUNDAY:System.out.println(4);break;default:throw new RuntimeException("What day is today?"+day);}}/*** 举例1:* jdk12中的写法:switch表达式,省去了break语句,避免了因少写break而出现case穿透*/@Testpublic void test2() {Week day = Week.FRIDAY;int num = 0;switch (day) {case MONDAY -> System.out.println(1);case TUESDAY, WEDNESDAY, THURSDAY -> System.out.println(2);case FRIDAY -> System.out.println(3);case SATURDAY, SUNDAY -> System.out.println(4);default -> throw new RuntimeException("What day is today?" + day);}}/*** 举例1:* jdk12中的写法:还可以使用变量接收switch表达式的结果*/@Testpublic void test3(){Week day = Week.FRIDAY;int num = 0;int result = switch (day) {case MONDAY -> 1;case TUESDAY, WEDNESDAY, THURSDAY ->2;case FRIDAY -> 3;case SATURDAY, SUNDAY -> 4;default -> throw new RuntimeException("What day is today?" + day);};System.out.println(result);}/*** 举例1:(在default中返回值5)* JDK13中的写法:引入了yield关键字,用于返回指定的数据,结束switch结构。* 这意味着,switch表达式(返回值)应该使用yield,switch语句(不返回值)应该使用break。* 和return的区别在于:return会直接跳出当前方法,而yield只会跳出当前switch块。*/@Testpublic void test4(){Week day = Week.FRIDAY;int num = 0;int result = switch (day) {case MONDAY -> {yield 1;}case TUESDAY, WEDNESDAY, THURSDAY -> {yield 2;}case FRIDAY -> {yield 3;}case SATURDAY, SUNDAY -> {yield 4;}default -> {System.out.println("值未找到");yield 5;}};System.out.println(result);}@Testpublic void test5(){Week day = Week.FRIDAY;int num = 0;int result = switch (day) {case MONDAY:yield 1;case TUESDAY, WEDNESDAY, THURSDAY:yield 2;case FRIDAY:yield 3;case SATURDAY, SUNDAY:yield 4;default:yield 5;};System.out.println(result);}}
block:
JDK13的预览特性 JDK14中二次预览特性 JDK15中功能转正
public class BlockTest {//对比1:@Testpublic void test1() {String info = "<html>\n" +" <body>\n" +" <p>Hello,尚硅谷</p>\n" +" </body>\n" +"</html>";System.out.println(info);}@Testpublic void test2() {String info = """<html><body><p>Hello,尚硅谷</p></body></html>""";System.out.println(info);}//对比2:@Testpublic void test3(){String myJson = "{\n" +" \"name\":\"Song Hongkang\",\n" +" \"gender\":\"男\",\n" +" \"address\":\"www.atguigu.com\"\n" +"}";System.out.println(myJson);}@Testpublic void test4(){String myJson1 = """{"name":"Song Hongkang","gender":"男","address":"www.atguigu.com"}""";System.out.println(myJson1);}//对比3@Testpublic void test5(){String query = "SELECT employee_id,last_name,salary,department_id\n"+"FROM employees\n" +"WHERE department_id IN (40,50,60)\n" +"ORDER BY department_id ASC";}@Testpublic void test6(){String newQuery = """SELECT employee_id,last_name,salary,department_idFROM employeesWHERE department_id IN (40,50,60)ORDER BY department_id ASC""";System.out.println(newQuery);}/*** JDK14新特性:* \:取消换行操作* \s:表示一个空格*/@Testpublic void test7(){String newQuery1 = """SELECT id,name,email \FROM customers\s\WHERE id > 4 \ORDER BY email DESC""";System.out.println(newQuery1);}
}
record:
JDK14中预览特性 JDK15中第二次预览特性 JDK16中转正特性
public class OrderTest {@Testpublic void test1(){Order order1 = new Order(1001,"orderAA");//测试toString()System.out.println(order1);//测试getter()System.out.println(order1.orderId());System.out.println(order1.orderName());Order order2 = new Order(1001,"orderAA");//测试equals()System.out.println(order1.equals(order2));//测试HashCode()和equals()HashSet<Order> set = new HashSet<>();set.add(order1);set.add(order2);System.out.println(set);}//测试Record@Testpublic void test2(){Order1 order1 = new Order1(1001,"orderAA");//测试toString()System.out.println(order1);//测试getter()System.out.println(order1.orderId());System.out.println(order1.orderName());Order1 order2 = new Order1(1001,"orderAA");//测试equals()System.out.println(order1.equals(order2));//测试HashCode()和equals()HashSet<Order1> set = new HashSet<>();set.add(order1);set.add(order2);System.out.println(set);}@Testpublic void test3(){Class<Person> clazz = Person.class;System.out.println(clazz.getSuperclass());}
}
Person
public record Person(int id, String name) {//-还可以在record声明类中定义静态字段、静态方法、构造器或实例方法。static String info = "我是一个人";public static void show() {System.out.println("我是一个人!");}public Person() {this(0, null);}public void test() {System.out.println("人吃饭");}//-不能在record声明的类中定义实例字段:类不能声明为abstract;不能声明显式的父类等。// final int age;
}
//abstract record Dog(int id){}
//record Cat(int id) extends Thread{}
//class Student extends Person{} //record声明的类不能有子类Order
public class Order {//属性:private final修饰private final int orderId;private final String orderName;//构造器中初始化属性public Order(int orderId,String orderName){this.orderId = orderId;this.orderName = orderName;}//提供属性的getter方法public int orderId() {return orderId;}public String orderName() {return orderName;}//equals()和hashCode()@Overridepublic boolean equals(Object o) {if (o == null || getClass() != o.getClass()) return false;Order order = (Order) o;return orderId == order.orderId && Objects.equals(orderName, order.orderName);}@Overridepublic int hashCode() {return Objects.hash(orderId, orderName);}@Overridepublic String toString() {return "Order{" +"orderId=" + orderId +", orderName='" + orderName + '\'' +'}';}
}
Order1
public record Order1(int orderId,String orderName) {
}
密封类的使用:
JDK15的预览特性J DK16二次预览特性 JDK17转正特性
//Person是一个密封类,可以被指定的子类所继承,非指定的类不能继承Person类
public sealed class Person permits Student, Teacher, Worker {
}
//要求指定的子类必须是final、sealed、non-sealed三者之一
final class Student extends Person {} //Student类不能被继承了
sealed class Teacher extends Person permits SeniorTeacher {} //Teacher类只能被指定的子类继承
non-sealed class SeniorTeacher extends Teacher{}
non-sealed class Worker extends Person {} //Worker类在被继承时,没有任何限制
class WatchWorker extends Worker{}
//class Farmer extends Person{}