Java是一门面向对象的编程语言 ,不仅吸收了C++ 语言的各种优点,还摒弃了C++里难以理解的多继承 、指针 等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。Java具有简单性、面向对象、分布式 、健壮性 、安全性 、平台独立与可移植性、多线程 、动态性等特点。 Java可以编写桌面应用程序 、Web应用程序、分布式系统 和嵌入式系统 应用程序等
JDK安装下载 下载jdk-17.0.12_windows-x64_bin.zip , 安装时可以选择安装地址,安装完成后配置JDK17的环境变量:
1 2 3 新增系统变量:JAVA_HOME,值为D:\IDEA\Java\jdk-17(安装路径) 新增系统变量:CLASSPATH,值为.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar,注意最前面的小黑点不能省. 在系统变量Path下新增两条配置:%JAVA_HOME%\bin和%JAVA_HOME%\jre\bin 
 
其他版本安装差不多,下载地址Java downloads 
 
Java8 新特性 原文链接:https://blog.csdn.net/qq_40991313/article/details/137256095 
1.基本介绍 
Lambda表达式 :Lambda表达式可以被视为一个对象,必须有上下文环境,作用是实现单方法的接口。该特性可以将功能视为方法参数,或者将代码视为数据。上下文环境意思是能证明它是对象,如让它处在方法或类的实参里,或者赋值给对象引用。
省略情况 :形参类型、返回类型可以省略,单参数能省略小括号,单语句能省略return、分号和大括号(全省略或全不省略) 
 
 
**方法引用**:引用已存在的Lambda表达式,达到相同的效果。引用已有Java类或对象(实例)的静态方法、实例方法、对象方法(System.out::println;)、构造器方法。可与Lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。 
**接口默认方法**:允许在接口中定义默认方法,默认方法必须使用default修饰。默认方法是接口中有方法体的方法,用于向已有的接口添加新的功能,而无需破坏现有的实现。实现类可以直接调用默认方法,也可以重写默认方法。 
**Stream API**:新添加的Stream API(java.util.stream)支持对元素流进行函数式操作。Stream API 集成在 Collections API 中,可以对集合进行批量操作(stream流的生成、操作、收集),例如filter()过滤、distinct()去重、map()加工、sorted()排序等操作。 
Date Time API新增LocalDate、LocalTime、DateTimeFormatter等类 :加强对日期与时间的处理。LocalDate、LocalTime可以获取本地时间。线程安全的DateTimeFormatter代替线程不安全的SimpleDateFormat,用于将日期和字符串之间格式转换。 
HashMap底层引入红黑树 :之前版本HashMap底层是“数组+链表”,当头插法的value链表长度大于等于8时,链表会转为红黑树,红黑树查询性能稳定O(logn),是近似平衡二叉树,层数最高2logn。 
ConcurrentHashMap降低锁的粒度 :JDK1.8之前采用分段锁,锁粒度是分段segment,JDK1.8采用synchronized+CAS,锁粒度是槽(头节点) 
CompletableFuture :是Future的实现类,JDK8引入,用于异步编排。 
JVM方法区的实现方式由永久代改为元空间 :元空间属于本地内存,由操作系统直接管理,不再受JVM管理。同时内存空间可以自动扩容,避免内存溢出。默认情况下元空间可以无限使用本地内存,也可以通过-XX:MetaspaceSize限制内存大小。 
 
2.Lambda表达式 Lambda 表达式是 Java 8 引入的一种新特性,主要用于实现单方法的接口,符合函数式思想。
 函数式思想: 在数学中,函数是一套计算方案,包含输入量和输出量,即“拿数据做操作”。 面向对象思想强调通过对象的形式来完成任务,而函数式思想则尽量忽略面向对象的复杂语法,强调“做什么”,而不是“以什么形式去做”。 Lambda表达式正是函数式思想的体现。它用来实现单方法接口的方法逻辑,实现过程中的参数可省略类型(因为类型已经在接口里声明过了),单个表达式时可以省略分号和大括号(因为只有单个语句,不用分号分割也不会有歧义)。
 
Lambda表达式实际是一个对象,形式是一个方法的逻辑:():{}。
例如前面TreeSet那块有提到过:
1 2 3 4 5 6 7 8 9 10 TreeSet<Dog> dogs = new  TreeSet <>(new  Comparator <Dog>() {     @Override      public  int  compare (Dog a, Dog b)  {         return  a.weight - b.weight;     } }); TreeSet<Dog> dogs = new  TreeSet <>((a, b) -> a.weight - b.weight); 
 
Lambda和匿名内部类区别: 
接口: Lambda只能是接口,匿名内部类可以是接口、抽象类、具体类。 
方法: Lambda只能单方法,匿名内部类可以多方法。 
原理: Lambda编译后字节码在运行时动态生成 ,匿名内部类编译后生成一个字节码文件 。 
 
 
基本语法
1 2 3 (参数列表) -> 单个表达式 或 (参数列表) -> { 表达式1 ;表达式2 ; } 
 
可省略内容:  
形参类型、返回类型可以省略; 
单参数能省略小括号; 
单语句能省略return、分号和大括号(全省略或全不省略) 
 
代码示例: 
形参类型、返回类型可以省略 。毕竟接口里也声明了类型,类型必须要么都写要么都省略。例如: 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public  class  Demo  {    public  static  void  main (String[] args)  {                                    fun((a,b)->a+b);     }     public  static  void  fun (Dog d) {         d.add(1 ,4 );     } }   public  interface  Dog  {         public  int  add (int  a,int  b) ; } 
 
3. Stream流 3.1 基本介绍 Stream 流是 Java 8 引入的一项新特性,用于对集合进行函数式编程风格的操作。它允许我们以声明性方式对数据进行过滤、加工、遍历、排序等操作,而不是以命令式方式逐个操作元素。 
特点 :
声明式编程 :使用流操作表达数据处理的意图,而不是具体的实现。声明式编程强调“做什么”而不是“怎么做”。在声明式编程中,程序员专注于描述要完成的任务或问题,而不是描述具体的实现步骤。Stream流把复杂啰嗦的代码改成一串简洁的代码,符合声明式编程。 
链式操作 :流操作可以链式调用,使代码更加简洁和易读。链式操作是利用运算符进行的连续运算(操作),如连续的赋值操作,而非拆成多条语句一个个加。例如stringBuilder.append(1).append(2);是链式操作,而stringBuilder.append(“a”);stringBuilder.append(“b”);不是链式操作。 
惰性求值 :流操作是惰性求值的,即只有在终端操作才会执行实际计算,map等中间操作不会直接计算求值。 
并行处理 :遍历的每一层之间是并发处理的,性能高。 
 
代码示例 : 先获取List的stream流,给集合中每个元素+2,然后升序排序、过滤只保留大于20的元素,最后收集成List类型的集合:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  class  Test  {    public  static  void  main (String[] args)  {         List<Integer> arrayList = new  ArrayList <>();         arrayList.add(10 );         arrayList.add(20 );         arrayList.add(30 );         arrayList.add(40 );         arrayList.add(50 );                  System.out.println("使用 Stream API 遍历并修改元素:" );         List<Integer> modifiedList = arrayList.stream()                 .map(num -> num + 2 ).sorted().filter(num -> num > 20 )                 .collect(Collectors.toList());                  System.out.println(modifiedList);     } } 
 
3.2 常用方法 3.2.1 生成操作 生成一个流
Stream.of(T... values):通过提供的值创建一个流。 
Stream.ofNullable(T t):通过单个值创建一个包含该值的流或一个空流。 
Arrays.stream(T[] array):通过数组创建一个流。 
Collection.stream():通过集合创建一个顺序流。 
Collection.parallelStream():通过集合创建一个并行流。 
Stream.generate(Supplier<T> s):生成一个无限流,元素由提供的 Supplier 生成。 
Stream.iterate(T seed, UnaryOperator<T> f):生成一个无限流,初始元素为 seed,后续元素由一元运算符生成。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  class  StreamGeneration  {    public  static  void  main (String[] args)  {                  List<String> list = new  ArrayList <String>();         Stream<String> listStream = list.stream();         Set<String> set = new  HashSet <String>();         Stream<String> setStream = set.stream();                  Map<String, Integer> map = new  HashMap <String, Integer>();         Stream<String> keyStream = map.keySet().stream();         Stream<Integer> valueStream = map.values().stream();         Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();                  String[] strArray = {"hello" , "world" , "java" };         Stream<String> strArrayStream = Stream.of(strArray);         Stream<String> strArrayStream2 = Stream.of("hello" , "world" , "java" );         Stream<Integer> intStream = Stream.of(10 , 20 , 30 );     } } 
 
3.2.2 中间操作 中间操作返回一个新的流,可以链式调用多个中间操作。
filter(Predicate predicate):过滤元素 
map(Function<T, R> mapper):加工,每个元素处理后返回一个新的元素。
map和filter区分:filter是满足条件的留下,是对原数组的过滤;map则是对原数组的加工,映射成一对一映射的新数组。 
 
 
mapToInt(ToIntFunction<? super T> mapper):返回一个 IntStream,除常规流式操作外,还可以取和、平均数等Integer的操作; 
concat():连接 
skip(long n):跳过n个元素 
distinct():去重 
sorted(比较器):排序 
limit(long maxSize):只截取前maxSize个元素 
 
filter:过滤 
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤掉空字符串,打印非空字符串。filter 的参数是 Lambda,Lambda 参数是 list 的每个元素,返回值是 Boolean,为 true 时留下。
1 2 3 List<String> list = Arrays.asList("abc" , "" , "bc" , "efg" , "abcd" , "" , "jkl" ); list.stream().filter(item -> !item.isEmpty()).forEach(System.out::println); 
 
skip & limit:跳过、限制 
1 2 3 List<String> list = Arrays.asList("abc" , "" , "bc" , "efg" , "abcd" , "" , "jkl" ); list.stream().skip(2 ).limit(2 ).forEach(System.out::println); 
 
concat 和 distinct:连接和去重 
1 2 3 Stream<String> s1 = Stream.of("a" , "b" , "c" ); Stream<String> s2 = Stream.of("b" , "c" , "d" ); Stream.concat(s1, s2).distinct().forEach(System.out::println); 
 
sorted 比较器: 
sorted() 方法返回由此流的元素组成的流,根据自然顺序排序。如:按字母序排序(sorted()参数可省,因为默认就是按字母序排序)
1 2 3 4 5 6 7 List<String> list = Arrays.asList("abc" , "" , "bc" , "efg" , "abcd" , "" , "jkl" ); list = list.stream().sorted((item1, item2) -> {     return  item1.compareTo(item2); }).collect(Collectors.toList()); System.out.println(list); 
 
map 
中间操作 map() 用法和 filter 类似,map 的参数是 Lambda,Lambda 参数是 list 的每个元素,返回值是加工后的 list 元素。
1 2 3 4 List<String> list = Arrays.asList("abc" , "" , "bc" , "efg" , "abcd" , "" , "jkl" ); list = list.stream().map(item -> item.toUpperCase()).collect(Collectors.toList()); System.out.println(list); 
 
mapToInt 
mapToInt 返回一个 IntStream,其中包含将给定函数应用于此流的元素的结果。IntStream 是由 Integer 元素组成的流,可以取和、平均数、排序、skip、limit、count、forEach  等。
1 2 3 4 5 6 List<String> list = Arrays.asList("10" , "20" , "30" ); list.stream().mapToInt(Integer::parseInt).forEach(System.out::println); int  sum  =  list.stream().mapToInt(Integer::parseInt).sum();System.out.println(sum); 
 
3.2.3 终端操作 终端操作触发流的计算,并返回一个结果或副作用。
forEach(Consumer action):对每个元素执行操作 
collect(Collector<T, A, R> collector):收集流的元素到一个集合或其他类型 
count():计算流中的元素数量 
 
count : count() 方法返回此流中的元素数量。
1 2 3 List<String> list = Arrays.asList("10" , "20" , "30" ); long  count  =  list.stream().mapToInt(Integer::parseInt).count();System.out.println(count);  
 
forEach : forEach(IntConsumer action) 方法对此流的每个元素执行操作。
1 2 List<String> list = Arrays.asList("10" , "20" , "30" ); list.stream().mapToInt(Integer::parseInt).forEach(value -> System.out.println(value)); 
 
collect :collect(Collector<T, A, R> collector):收集流的元素到一个集合或其他类型
public static  Collector toList(): 把元素收集到 List 集合中  
public static  Collector toSet(): 把元素收集到 Set 集合中  
public static Collector toMap(Function keyMapper, Function valueMapper): 把元素收集到 Map 集合中 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 List<String> list = new  ArrayList <>(); list.add("123" ); list.add("4567" ); List<String> ansList = list.stream().filter(item -> item.length() == 3 ).collect(Collectors.toList()); System.out.println(ansList); List<Integer> ansList1 = list.stream().map(Integer::parseInt).collect(Collectors.toList()); System.out.println(ansList1); Set<Integer> ansList2 = list.stream().map(Integer::parseInt).collect(Collectors.toSet()); System.out.println(ansList2); Map<String, Integer> stringSizeMap = list.stream().collect(Collectors.toMap(item -> item, item -> item.length())); System.out.println(stringSizeMap); String  ansString  =  list.stream().collect(Collectors.joining("," ));System.out.println(ansString); 
 
4. 函数式接口 4.1 基本介绍 函数式接口是指仅包含一个抽象方法的接口,可以使用 Lambda 表达式或方法引用来创建该接口的实例。Java 8 引入了函数式接口,并在java.util.function 包中提供了许多预定义的函数式接口,例如 Function、Supplier、Consumer、Predicate 等。 
函数式接口 :有且仅有一个抽象方法的接口。 Java中函数式编程体现就是Lambda表达式。
函数式接口注解 :@FunctionalInterface
如果方法的返回值是函数式接口,可以使用Lambda表达式作为结果返回。
格式 : 函数式接口对象作为一个方法的形参,实参是Lambda表达式。
常见的函数式接口 :
JDK自带一些函数式接口 :函数式接口Supplier中get获取有返回值的数据,Predicate中test返回boolean型数据,Consumer中accept无返回值数据操作。
接口  
方法  
作用  
示例  
 
 
Supplier 
get(),返回各类型的数据 
获取 
返回数组最大值 
 
Function 
apply(),返回各类型数据 
转换 
数字字符串转换 
 
Predicate 
test(),返回boolean型数据 
判断 
判断数字是否大于5 
 
Consumer 
accept(),无返回值 
操作 
翻转字符串 
 
4.2 生产者接口Supplier 作用: 获取到生产出的数据
Supplier译作生产者,生产的数据类型由泛型参数T指定。
示例: 例如生产者接口,创建一个方法,获取数组的最大值,实际的获取逻辑由Lambda表达式确认:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public  class  Test  {    public  static  void  main (String[] args)  {                  int [] arr = {19 , 50 , 28 , 37 , 46 };                  int  maxValue  =  getMax(() -> {             int  max  =  arr[0 ];             for  (int  i : arr) {                 if  (i > max) {                     max = i;                 }             }             return  max;         });                    System.out.println("数组中的最大值是: "  + maxValue);     }          private  static  int  getMax (Supplier<Integer> sup)  {         return  sup.get();     } } 
 
4.3 函数式接口Consumer 作用: 对数据进行操作,无返回值。
Consumer是消费型接口,消费的数据类型由泛型指定。
代码示例: 两种方式和一种方式消费字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public  class  Test  {    public  static  void  main (String[] args)  {         String  name  =  "Hello World" ;                  operatorString(name, str -> System.out.println("转大写:"  + str.toUpperCase()), str ->                        System.out.println("转小写:" +str.toLowerCase()));                  operatorString(name, str -> System.out.println("空格替换成下划线:"  + str.replace(" " , "_" )));     }          private  static  void  operatorString (String name, Consumer<String> con1, Consumer<String> con2)  {                  System.out.println("第一个消费者消费一次" );         con1.accept(name);                  System.out.println("第二个消费者消费一次" );         con2.accept(name);                  System.out.println("第一个消费者组合第二个消费者,再组合第一个消费者,按顺序各消费一次" );         con1.andThen(con2).andThen(con1).accept(name);     }          private  static  void  operatorString (String name, Consumer<String> con)  {         con.accept(name);     }   } 
 
4.4 函数式接口Predicate Predicate接口用于表示布尔值函数,判断参数是否满足条件。它接受一个参数,并返回一个布尔值。
译作谓词,谓语。
方法签名 
说明 
 
 
boolean test(T t) 
对给定的参数进行判断(谓词操作)。返回布尔值。 
 
default Predicate and(Predicate<? super T> other)  
返回一个组合的 Predicate,表示逻辑与(AND)操作。 
 
default Predicate negate()  
返回一个表示逻辑非(NOT)操作的 Predicate。 
 
default Predicate or(Predicate<? super T> other)  
返回一个组合的 Predicate,表示逻辑或(OR)操作。 
 
方法的形参Predicate,接受的实参是Lambda参数。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public  class  Test  {    public  static  void  main (String[] args)  {                           boolean  result  =  checkString("hello" ,                 s -> s.length() > 5 ,                 s -> s.length() < 100 );         System.out.println(result);                           System.out.println(negateCheck("hello" , s->s.length() == 5 ));     }          private  static  boolean  checkString (String s, Predicate<String> p1, Predicate<String> p2)  {         return  p1.and(p2).test(s);     }          private  static  boolean  negateCheck (String s, Predicate<String> p)  {         return  p.negate().test(s);     } } 
 
4.5 方法引用 4.5.1 概念 方法引用跟Lambda类似,都可以根据上下文推导。格式: 
 
4.5.2 引用实例方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public  class  Test  {    public  static  void  main (String[] args)  {                  TreeSet<Dog> dogsLambda = new  TreeSet <>((a, b) -> a.weight - b.weight);                  TreeSet<Dog> dogsMethodRef = new  TreeSet <>(Test::compareDogsByWeight);                  dogsLambda.add(new  Dog (10 , "旺财" ));         dogsLambda.add(new  Dog (5 , "小黑" ));         dogsLambda.add(new  Dog (15 , "小白" ));         dogsMethodRef.add(new  Dog (10 , "旺财" ));         dogsMethodRef.add(new  Dog (5 , "小黑" ));         dogsMethodRef.add(new  Dog (15 , "小白" ));                  System.out.println("1.使用Lambda表达式打印结果:" );         dogsLambda.forEach(dog->{             System.out.println(dog);         });         System.out.println("2.使用方法引用,引用PrintStream类的println方法:" );         dogsMethodRef.forEach(System.out::println);     }          public  static  int  compareDogsByWeight (Dog a, Dog b)  {         return  a.weight - b.weight;     } } public  class  Dog  {    int  weight;     String name;       public  Dog (int  weight, String name)  {         this .weight = weight;         this .name = name;     }       @Override      public  String toString ()  {         return  "Dog{"  +                 "weight="  + weight +                 ", name='"  + name + '\''  +                 '}' ;     }     @Override      public  boolean  equals (Object o)  {         if  (this  == o) {             return  true ;         }         if  (o == null  || getClass() != o.getClass()) {             return  false ;         }         Dog  dog  =  (Dog) o;         return  weight == dog.weight && Objects.equals(name, dog.name);     }       @Override      public  int  hashCode ()  {         return  Objects.hash(weight, name);     } } 
 
打印结果
1.使用Lambda表达式打印结果: Dog{weight=5, name=’小黑’} Dog{weight=10, name=’旺财’} Dog{weight=15, name=’小白’} 2.使用方法引用,引用PrintStream类的println方法: Dog{weight=5, name=’小黑’} Dog{weight=10, name=’旺财’} Dog{weight=15, name=’小白’}
 
4.6 引用构造器 某些场景下,需要在使用时才确定创建对象的逻辑,这时就可以引用构造器。格式: 
 
代码示例: 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public  class  Test  {    public  static  void  main (String[] args)  {                  builderLinQinXia((name, age) -> new  Student (name, age));         builderZhangXueYou((name, age) -> new  Student (name, age));                  builderLinQinXia(Student::new );         builderZhangXueYou(Student::new );     }          private  static  void  builderLinQinXia (StudentBuilder sb)  {         Student  s  =  sb.build("林青霞" , 30 );         System.out.println(s.getName() + " "  + s.getAge());     }          private  static  void  builderZhangXueYou (StudentBuilder sb)  {         Student  s  =  sb.build("张学友" , 26 );         System.out.println(s.getName() + " "  + s.getAge());     } } class  Student  {    private  String name;     private  int  age;     public  Student (String name, int  age)  {         this .name = name;         this .age = age;     }     public  String getName ()  {         return  name;     }     public  int  getAge ()  {         return  age;     } } @FunctionalInterface interface  StudentBuilder  {    Student build (String name, int  age) ; } 
 
4.7 接口组成更新 java8后加入了默认方法、静态方法。java9后加入了私有方法。
4.7.1 接口默认方法 接口中的方法会被隐式指定为 public abstract方法,抽象方法不能有实际内容。但某些业务场景需在接口中扩展一些有业务逻辑的方法,又不想直接改成抽象类(因为抽象类只能单继承),这时,JDK8扩展了接口的默认方法,需要用default关键字修饰方法。格式 :
default 返回值 方法名(参数) {
    ...
}
 
 特点: 
默认方法可以有方法体 
默认方法可被接口的实现类对象调用。 
默认方法不是抽象方法,实现类可以重写,也可以不重写,同名冲突时必须重写(某个类实现了多个包含默认方法fun()的接口,为了防止冲突,此时实现类必须重写这个类)。 
 
 示例: 
1 2 3 4 5 6 7 8 9 public  interface  MyInterface  {         void  abstractMethod () ;          default  void  defaultMethod ()  {         System.out.println("这是接口的默认方法" );     } } 
 
4.7.2 接口静态方法 在 Java 8 中,引入了接口静态方法。接口静态方法与类静态方法类似,但它们属于接口本身,而不是接口的实现类。静态方法常用于在接口中提供静态工具方法,帮助操作或处理与接口相关的数据。格式 与类的静态方法一致: 
static 返回类型 方法名(参数列表) {
    // 方法体
}
 
特点 :
命名冲突时要重写:因为Java是单继承多实现的,所以存在一个类实现多个接口的情况。如果一个类同时实现了多个接口,并且这些接口都有相同签名的默认方法,则必须在实现类中重写该方法以解决冲突。例如类A实现了有同名静态方法的接口B、C,则A的对象分不清调用哪个接口的方法。 
扩展接口功能:默认方法允许在不破坏现有实现的情况下扩展接口功能,对现有功能影响较小,符合设计模式中的开闭原则。 
接口中静态方法跟类的静态方法,属于“类方法”,先于对象产生,所以只能被接口名调用,不能被实现类对象调用。 
 
示例 :
1 2 3 4 5 6 public  interface  MyInterface  {         static  void  staticMethod ()  {         System.out.println("这是接口的静态方法" );     } } 
 
4.7.3 JDK9接口私有方法 接口中的方法会被隐式的指定为 public abstract方法。为了将接口中多个默认或静态方法中的共性方法抽离出来,JDK9引入了接口私有方法。接口私有方法只能在接口内部,被接口静态方法或者接口默认方法调用,不能在接口外部或实现类中调用。格式 :
1 2 3 4 5 6 7 private  返回类型 方法名(参数列表) {     } private  static  返回类型 方法名(参数列表) {     } 
 
特点 :
示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public  class  Dog  implements  Animal  {    public  static  void  main (String[] args)  {         Dog  dog  =  new  Dog ();         dog.eat();         Animal.staticMethod();     } } public  interface  Animal  {    default  void  eat ()  {         System.out.println("动物在吃东西" );         privateSoundMethod();     }          private  void  privateSoundMethod ()  {         System.out.println("这是私有实例方法,接口内私有、静态、默认方法都可以调用它:发出声音" );     }          static  void  staticMethod ()  {         System.out.println("静态方法调用私有静态方法" );         privateStaticMethod();     }          private  static  void  privateStaticMethod ()  {         System.out.println("这是私有静态方法,它只能被接口中的静态方法调用" );     } } 
 
运行结果:
静态方法调用私有静态方法 这是私有静态方法,它只能被接口中的静态方法调用 动物在吃东西 这是私有实例方法,接口内私有、静态、默认方法都可以调用它:发出声音
 
 
Java11 新特性 原文链接:https://blog.csdn.net/qq_43947876/article/details/148399400 
一、标准化HTTP Client:告别HttpURLConnection 1.1 HttpURLConnection 的痛点 在 Java 11 之前,开发者主要使用 HttpURLConnection 处理 HTTP 请求,但存在严重缺陷:
设计陈旧 :
 
功能缺失 :
不支持 HTTP/2。
 
缺乏异步处理能力。
 
无内置的 WebSocket 支持。
 
难以处理 cookie 和重定向。
 
 
 
代码冗长 :
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 URL  url  =  new  URL ("https://api.example.com" );HttpURLConnection  conn  =  (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET" ); int  status  =  conn.getResponseCode();                          if  (status == 200 ) {    try  (BufferedReader  in  =  new  BufferedReader (         new  InputStreamReader (conn.getInputStream()))) {         String line;         StringBuilder  content  =  new  StringBuilder ();         while  ((line = in.readLine()) != null ) {             content.append(line);         }         System.out.println(content);     } } else  {      } conn.disconnect(); 
 
1.2 标准化 HTTP Client 的解决方案 核心设计原理:
Java 11 的标准化 HTTP Client 采用分层异步架构,核心通过 协议协商机制 自动选择最佳协议(优先尝试 HTTP/2,失败时降级到 HTTP/1.1),利用 多路复用技术 在单个 TCP 连接上并行处理多个请求,通过 响应式流处理模型 实现非阻塞 I/O 操作。其内部基于 CompletableFuture 实现异步处理引擎,配合智能 连接池管理 减少连接建立开销,同时通过 类型安全的 BodyHandler/BodyPublisher 抽象层实现请求/响应体的灵活转换,最终解决了传统 HttpURLConnection 的同步阻塞、协议支持不足和 API 臃肿三大痛点,为现代网络编程提供了高性能、可扩展的标准解决方案。
1.3 实战应用指南 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 HttpClient  client  =  HttpClient.newBuilder()      .version(HttpClient.Version.HTTP_2)                     .connectTimeout(Duration.ofSeconds(10 ))       .followRedirects(HttpClient.Redirect.ALWAYS)            .authenticator(Authenticator.getDefault())              .build(); HttpRequest  request  =  HttpRequest.newBuilder()      .uri(URI.create("https://api.example.com/users" ))       .header("Content-Type" , "application/json" )       .header("Authorization" , "Bearer token" )       .timeout(Duration.ofSeconds(15 ))       .GET()                                                 .build(); HttpResponse<String> response = client.send(       request,        HttpResponse.BodyHandlers.ofString() ); System.out.println("状态码: "  + response.statusCode()); System.out.println("响应体: "  + response.body()); client.sendAsync(request, HttpResponse.BodyHandlers.ofString())       .thenApply(HttpResponse::body)       .thenAccept(body -> {           System.out.println("异步响应: "  + body);                  })       .exceptionally(e -> {           System.err.println("请求失败: "  + e.getMessage());           return  null ;       }); String  jsonBody  =  "{\"name\":\"John\", \"age\":30}" ;HttpRequest  postRequest  =  HttpRequest.newBuilder()      .uri(URI.create("https://api.example.com/users" ))       .header("Content-Type" , "application/json" )       .POST(HttpRequest.BodyPublishers.ofString(jsonBody))       .build(); HttpRequest  fileUpload  =  HttpRequest.newBuilder()      .uri(URI.create("https://api.example.com/upload" ))       .header("Content-Type" , "multipart/form-data" )       .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("data.txt" )))       .build(); WebSocket  webSocket  =  HttpClient.newHttpClient()      .newWebSocketBuilder()       .buildAsync(URI.create("wss://echo.websocket.org" ), new  WebSocket .Listener() {                      @Override            public  CompletionStage<?> onText(WebSocket webSocket,                                            CharSequence data,                                            boolean  last) {               System.out.println("收到消息: "  + data);               return  null ;           }                      @Override            public  void  onOpen (WebSocket webSocket)  {               webSocket.sendText("Hello Server!" , true );           }       }).join(); 
 
1.4 使用建议  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 .timeout(Duration.ofSeconds(10 ))  .connectTimeout(Duration.ofSeconds(5 ))  HttpResponse<Path> response = client.send(      request,      HttpResponse.BodyHandlers.ofFile(Paths.get("output.txt" )) ); HttpResponse<InputStream> streamResponse = client.send(      request,      HttpResponse.BodyHandlers.ofInputStream() ); try  {     HttpResponse<String> response = client.send(...); } catch  (IOException | InterruptedException e) {       } catch  (HttpTimeoutException e) {       } 
 
1.5 完整 HTTP Client 使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public  class  AdvancedHttpClientExample  {    private  static  final  HttpClient  CLIENT  =  HttpClient.newHttpClient();          public  CompletableFuture<JsonObject> fetchUserData (String userId)  {         HttpRequest  request  =  HttpRequest.newBuilder()                 .uri(URI.create("https://api.example.com/users/"  + userId))                 .header("Accept" , "application/json" )                 .timeout(Duration.ofSeconds(8 ))                 .build();                  return  CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())                 .thenApply(response -> {                     if  (response.statusCode() == 200 ) {                         return  parseJson(response.body());                     } else  {                         throw  new  RuntimeException ("HTTP Error: "  + response.statusCode());                     }                 });     }          private  JsonObject parseJson (String body)  {                  return  ...;     } } 
 
1.6 总结 Java 11 的标准化 HTTP Client 解决了传统网络编程的三大痛点:
协议落后 → 支持 HTTP/2 和 WebSocket 
性能低下 → 异步非阻塞 + 连接复用 
API 繁琐 → 链式调用 + 响应式处理 
 
二、局部变量类型推断增强:Lambda中的var 先说一下什么是java中的var类型,Java 中的 var 是 JDK 10 引入的局部变量类型推断关键字,允许编译器根据赋值语句右侧的表达式自动推断变量类型,从而简化代码编写。
2.1 解决的问题:类型声明的一致性困境 在 Java 10 引入 var 后,开发者面临一个矛盾:
1 2 3 4 5 6 var  list  =  new  ArrayList <String>();     (var  s) -> s.length()                       (s) -> s.length()                           
 
这种不一致性就导致了:
代码风格割裂 :普通变量和 Lambda 参数使用不同规则。 
注解无法应用 :无法给隐式类型参数添加注解。 
可读性降低 :复杂 Lambda 难以理解参数类型。 
 
2.2 实现原理:编译器的类型推导增强 Java 11 通过 JEP 323 扩展了编译器的类型推导能力:
这种方式根据方法签名推导参数类型,通过函数式接口传递类型信息并且允许在 var 上添加注解。 编译过程 :
1 2 3 4 5 6 7 Function<String, Integer> len = (var  s) -> s.length(); 1.  根据左侧 Function<String, Integer> 确定目标类型2.  解析 var  s → 推导为 String 类型3.  验证 s.length() 返回 int  (兼容 Integer)
 
编译器处理步骤 :
词法分析 :识别 var 关键字
 
语法树构建 :创建带 var 的 Lambda 节点
 
类型绑定 :
从赋值上下文获取目标类型
 
解析函数式接口的泛型参数
 
将 var 绑定到具体类型
 
 
 
注解附加 :将参数注解关联到具体类型
 
 
2.3 实战应用指南 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Function<String, Integer> lengthFunc =      (@NonNull  var  str) -> str.length();                   Function<String, Integer> oldFunc =      str -> str.length();                                   BiFunction<Integer, Double, String> format =      (var  num, var  dec) -> String.format("%d-%.2f" , num, dec); BiFunction<Integer, Double, String> explicit =      (Integer num, Double dec) -> ...; List<Object> mixedList = Arrays.asList("Text" , 42 , 3.14 ); mixedList.forEach((var  obj) -> {     if  (obj instanceof  String) {         System.out.println(((String) obj).toUpperCase());       } }); 
 
适用场景: 
1 2 3 4 5 6 7 8 9 10 (var  @Email  email) -> validate(email) Map<String, List<Map<Integer, Set<String>>>> complex = ...; complex.forEach((var  key, var  value) -> ...); (var  userId, var  timestamp) -> process(userId, timestamp) 
 
禁用场景: 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 var  lambda  =  (var  x) -> x * 2 ;  (var  x, y) -> x + y   Function<Number, String> func =      (var  n) -> n.toString();   Consumer<String> consumer =      (var  n) -> System.out.println(n);   Object  ambiguous  =  (var  n) -> n.toString(); 
 
2.4 终极示例:结合注解和复杂类型 Java 11 的这项改进并非鼓励在所有 Lambda 中使用 var,而是提供选择性显式类型声明的能力,在保持类型安全的同时增加灵活性。
1 2 3 4 5 6 7 8 9 10 11 12 13 public  class  UserProcessor  {    public  void  processUsers (List<@Valid  User> users)  {         users.forEach((var  user) -> {             @NonEmpty  String  name  =  validateName(user.getName());             sendWelcomeEmail(user.getEmail());         });     }          private  String validateName (@NonEmpty  String name)  {         if (name.isBlank()) throw  new  IllegalArgumentException ();         return  name.strip();     } } 
 
三、文件读写简化 3.1 文件操作的”样板代码地狱” 在 Java 11 之前,读写文件需要大量重复代码,如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Path  path  =  Paths.get("demo.txt" );String content; try  (BufferedReader  reader  =  Files.newBufferedReader(path)) {    StringBuilder  sb  =  new  StringBuilder ();     String line;     while  ((line = reader.readLine()) != null ) {         sb.append(line).append("\n" );     }     content = sb.toString(); } catch  (IOException e) {      } List<String> lines = Arrays.asList("Line1" , "Line2" ); try  (BufferedWriter  writer  =  Files.newBufferedWriter(path)) {    for  (String line : lines) {         writer.write(line);         writer.newLine();     } } catch  (IOException e) {      } 
 
传统方式存在几大痛点:
代码冗长 :简单操作需要10+行代码 
资源管理复杂 :必须显式关闭流(忘记关闭会导致资源泄漏) 
异常处理繁琐 :必须处理 IOException 
字符集问题 :默认使用平台编码,跨平台可能乱码 
 
3.2 实现原理:智能封装与最佳实践 Java 11 通过 Files 类新增方法实现简化:
1 2 3 4 5 6 7 8 9 10 11 12 public  static  String readString (Path path)  throws  IOException {    return  readString(path, StandardCharsets.UTF_8);  } public  static  Path writeString (Path path, CharSequence csq, OpenOption... options)      throws  IOException {     try  (BufferedWriter  writer  =  newBufferedWriter(path, UTF_8, options)) {         writer.write(csq.toString());     }     return  path; } 
 
关键技术原理 :
自动资源管理 : 使用 try-with-resources 确保流自动关闭 
智能缓冲 : 内部使用 BufferedWriter/BufferedReader 优化性能 
字符集安全 : 默认 UTF-8 解决跨平台乱码问题 
异常透明 : 保留必要的 IOException 传播 
 
3.3 实战应用指南 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 Path  file  =  Path.of("data.txt" );Files.writeString(file, "Hello Java 11!" ); Files.writeString(file, "\n追加内容" , StandardOpenOption.APPEND); String  content  =  Files.readString(file);System.out.println(content);  Files.writeString(file, "日本語テキスト" , StandardCharsets.UTF_8); String  jpText  =  Files.readString(file, StandardCharsets.UTF_8);Files.writeString(file, "新内容" ,      StandardOpenOption.CREATE,      StandardOpenOption.APPEND); Files.writeString(file, "独占内容" ,      StandardOpenOption.WRITE,      StandardOpenOption.CREATE_NEW); try  {    String  config  =  Files.readString(Path.of("config.cfg" ));      } catch  (NoSuchFileException e) {     System.err.println("配置文件不存在: "  + e.getFile()); } catch  (AccessDeniedException e) {     System.err.println("无访问权限: "  + e.getFile()); } catch  (IOException e) {     System.err.println("系统IO错误: "  + e.getMessage()); } 
 
高级应用场景 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 WatchService  watcher  =  FileSystems.getDefault().newWatchService();Path  confDir  =  Path.of("config" );confDir.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY); while  (true ) {    WatchKey  key  =  watcher.take();     for  (WatchEvent<?> event : key.pollEvents()) {         if  (event.context().toString().equals("app.conf" )) {             reloadConfig(confDir.resolve("app.conf" ));         }     }     key.reset(); } private  void  reloadConfig (Path configFile)  throws  IOException {    String  newConfig  =  Files.readString(configFile);      } List<Path> textFiles = Files.list(Path.of("docs" ))     .filter(p -> p.toString().endsWith(".txt" ))     .toList(); textFiles.parallelStream()     .map(p -> {         try  {             return  Files.readString(p);         } catch  (IOException e) {             return  "" ;          }     })     .filter(text -> text.contains("Java 11" ))     .forEach(content -> processContent(content)); String  template  =  Files.readString(Path.of("template.html" ));Map<String, String> variables = Map.of(     "${name}" , "张三" ,     "${email}" , "zhangsan@example.com"  ); for  (Map.Entry<String, String> entry : variables.entrySet()) {    template = template.replace(entry.getKey(), entry.getValue()); } Files.writeString(Path.of("output.html" ), template); 
 
性能优化与注意事项 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Path  largeFile  =  Path.of("huge.log" );long  size  =  Files.size(largeFile);if  (size > 100  * 1024  * 1024 ) {          try  (Stream<String> lines = Files.lines(largeFile)) {         lines.filter(line -> line.contains("ERROR" ))              .forEach(System.err::println);     } } else  {     String  content  =  Files.readString(largeFile);      } public  Charset detectCharset (Path file)  throws  IOException {    byte [] bom = new  byte [4 ];     try  (InputStream  is  =  Files.newInputStream(file)) {         is.read(bom);     }     if  (bom[0 ] == (byte ) 0xEF  && bom[1 ] == (byte ) 0xBB  && bom[2 ] == (byte ) 0xBF ) {         return  StandardCharsets.UTF_8;     } else  if  (bom[0 ] == (byte ) 0xFE  && bom[1 ] == (byte ) 0xFF ) {         return  StandardCharsets.UTF_16BE;     } else  {         return  StandardCharsets.UTF_8;      } } 
 
3.4 终极示例:完整的配置加载器 Java 11的Files API通过readString()和writeString()方法,用单行代码彻底简化了文件读写操作,自动处理资源关闭、字符编码(默认UTF-8)和缓冲优化,解决了传统IO冗长的样板代码问题,使文本文件操作变得直观高效,适用于配置加载、日志处理等常见场景,虽对超大文件略有性能损耗,但显著提升了开发效率和代码可维护性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public  class  ConfigLoader  {    private  final  Path configPath;     private  Map<String, String> settings = new  HashMap <>();     public  ConfigLoader (String filename)  {         this .configPath = Path.of("conf" , filename);     }     public  void  load ()  throws  IOException {         String  content  =  Files.readString(configPath, StandardCharsets.UTF_8);         content.lines()                .filter(line -> !line.startsWith("#" ) && !line.isBlank())                .map(line -> line.split("=" , 2 ))                .forEach(parts -> {                    if  (parts.length == 2 ) {                        settings.put(parts[0 ].strip(), parts[1 ].strip());                    }                });     }     public  void  save ()  throws  IOException {         StringBuilder  sb  =  new  StringBuilder ("# 自动生成的配置\n" );         settings.forEach((k, v) -> sb.append(k).append("=" ).append(v).append("\n" ));         Files.writeString(configPath, sb.toString(),              StandardOpenOption.TRUNCATE_EXISTING,             StandardOpenOption.CREATE);     } } 
 
四、ZGC 与 Epsilon 4.1 痛点问题 传统 GC 的局限性:
STW 停顿时间过长 :
CMS/G1 在 TB 级堆内存下停顿可达秒级
 
无法满足金融交易、实时系统等低延迟需求
 
 
 
内存回收效率问题 :
 
特殊场景缺失 :
 
 
4.2 ZGC:亚毫秒级停顿的突破 核心原理 :
ZGC的核心原理是通过并发着色指针和读屏障技术实现亚毫秒级停顿:
着色指针在64位地址中嵌入元数据(标记/重映射状态),使GC线程能并发标记对象;
 
读屏障在应用线程访问对象时即时修复指针引用,实现堆压缩与标记的并发执行;
 
全阶段并发(标记/转移/重定位)仅需<1ms的STW根扫描,使停顿时间与堆大小无关。 其本质是以空间换时间(保留内存屏障开销)和以CPU换延迟(并发处理),适用于TB级堆内存的低延迟场景。
 
 
ZGC 发展路线 :
Java 15:正式生产可用 
Java 17:分代 ZGC (减少内存开销) 
Java 21:弹性元空间 (减少 native 内存) 
 
4.3 Epsilon:无操作 GC Epsilon GC(无操作垃圾收集器)的核心原理是只分配内存,不回收内存,通过彻底消除GC开销来实现极致性能:
内存分配 :使用bump-the-pointer线性分配和TLAB(线程本地缓冲)快速分配对象 
内存不回收 :完全跳过标记/清除/压缩等回收阶段,堆耗尽时直接OOM 
零开销 :无GC线程、无写屏障、无内存扫描,CPU利用率接近100% 
 
设计哲学 :用内存换性能,适合短期任务和性能基准测试,但需确保应用生命周期内堆不耗尽。
4.4 实战应用指南 ZGC 启用与调优:
1 2 3 4 5 6 7 8 9 10 java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -jar app.jar java -XX:+UseZGC \      -Xmx16g \                                -XX:ConcGCThreads=4 \                    -XX:ZAllocationSpikeTolerance=5 \        -Xlog:gc*:file=gc.log \                  -jar trading-system.jar 
 
Epsilon 使用场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 java -XX:+UnlockExperimentalVMOptions \      -XX:+UseEpsilonGC \      -Xmx1g \      -jar benchmark.jar java -XX:+UseEpsilonGC \      -Xmx128m \      -jar lambda-function.jar java -XX:+UseEpsilonGC \      -XX:+HeapDumpOnOutOfMemoryError \      -Xmx100m \      -jar memory-test.jar 
 
4.5 总结 ZGC、Epsilon和G1的选型核心在于权衡延迟、内存与吞吐需求 : ZGC凭借并发着色指针实现亚毫秒级停顿,适合TB级堆内存的低延迟场景(如金融交易);Epsilon彻底放弃垃圾回收,以零GC开销服务于短期任务和性能测试;而G1作为Java默认收集器,通过分Region混合回收平衡吞吐与延迟(200ms内),是通用服务的最佳选择。三者分别覆盖了极致延迟、无GC干扰和通用稳定的三大技术象限,开发者需根据堆大小、任务生命周期和延迟要求精准匹配。
 
Java17 新特性 原文链接:https://cloud.tencent.com/developer/article/2475140 
Java 17是Java编程语言的最新版本,于2021年9月14日发布。以下是Java 17的一些新特性:
 Sealed类和接口 :Sealed类和接口限制了继承和实现的范围,在编译时提供更强的封装性。  
 Pattern匹配 :Pattern匹配简化了对实例进行类型检查和转换的流程,使代码更加简洁和易读。  
 垃圾收集器(G1)的改进 :Java 17对G1垃圾收集器进行了改进,包括改进了内存分配、暂停时间优化和垃圾回收性能等方面。  
 Oracle数据库 连接的改进 :Java 17引入了一个新的API,使开发人员可以更轻松地与Oracle数据库进行连接和交互。  
 嵌套的JVM标签 :Java 17支持在字节码层面上为代码添加标签,以便在运行时进行检查和验证。  
 私有嵌套接口 :Java 17允许在接口内部定义私有嵌套接口,以实现更好的封装性和模块化。  
 静态成员类型引用 :Java 17允许使用静态成员类型引用,以简化代码并提高可读性。  
 UNIX域套接字通道 :Java 17引入了对UNIX域套接字通道的支持,允许Java程序通过UNIX套接字与本地进程进行通信。 
 
原文链接:https://blog.csdn.net/m0_53548081/article/details/147604067 
1. 密封类(Sealed Classes) 密封类允许开发者精确控制哪些类可以继承或实现一个类或接口,增强了Java的封装性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public  sealed  interface  Shape  permits Circle, Rectangle, Triangle {    double  area () ; }   public  final  class  Circle  implements  Shape  {    private  final  double  radius;          public  Circle (double  radius)  {         this .radius = radius;     }          @Override      public  double  area ()  {         return  Math.PI * radius * radius;     } } public  final  class  Rectangle  implements  Shape  {    private  final  double  width;     private  final  double  height;          public  Rectangle (double  width, double  height)  {         this .width = width;         this .height = height;     }          @Override      public  double  area ()  {         return  width * height;     } } public  final  class  Triangle  implements  Shape  {    private  final  double  base;     private  final  double  height;          public  Triangle (double  base, double  height)  {         this .base = base;         this .height = height;     }          @Override      public  double  area ()  {         return  0.5  * base * height;     } } public  static  String getShapeDescription (Shape shape)  {    return  switch  (shape) {         case  Circle c -> "圆形,面积: "  + c.area();         case  Rectangle r -> "矩形,面积: "  + r.area();         case  Triangle t -> "三角形,面积: "  + t.area();              }; } 
 
2.记录类(Records) Records为创建不可变数据传输对象(DTO)提供了简洁的语法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public  class  PersonTraditional  {    private  final  String name;     private  final  int  age;          public  PersonTraditional (String name, int  age)  {         this .name = name;         this .age = age;     }     public  String getName ()  { return  name; }     public  int  getAge ()  { return  age; }          @Override      public  boolean  equals (Object o)  {         if  (this  == o) return  true ;         if  (o == null  || getClass() != o.getClass()) return  false ;         PersonTraditional  that  =  (PersonTraditional) o;         return  age == that.age && Objects.equals(name, that.name);     }     @Override      public  int  hashCode ()  {         return  Objects.hash(name, age);     }     @Override      public  String toString ()  {         return  "PersonTraditional{name='"  + name + "', age="  + age + '}' ;     } }   public  record  Person (String name, int  age)  {              public  boolean  isAdult ()  {         return  age >= 18 ;     }          public  Person {         if  (age < 0 ) {             throw  new  IllegalArgumentException ("Age cannot be negative" );         }     } } public  class  RecordsExample  {    public  static  void  main (String[] args)  {                  Person  person  =  new  Person ("张三" , 30 );                  System.out.println("姓名: "  + person.name());         System.out.println("年龄: "  + person.age());                  System.out.println("是否成年: "  + person.isAdult());                  var  userInfo  =  getUserInfo();         processUserData(userInfo.username(), userInfo.email());     }          private  static  UserInfo getUserInfo ()  {         return  new  UserInfo ("admin" , "admin@example.com" );     }          private  static  void  processUserData (String username, String email)  {         System.out.println("处理用户: "  + username + ", 邮箱: "  + email);     } } record  UserInfo (String username, String email)  {}
 
3. 模式匹配for instanceof Java 17改进了instanceof运算符,使其能够同时进行类型检查和类型转换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public  String getDescriptionTraditional (Object obj)  {    if  (obj instanceof  String) {         String  s  =  (String) obj;         return  "字符串,长度: "  + s.length();     } else  if  (obj instanceof  Integer) {         Integer  i  =  (Integer) obj;         return  "整数: "  + i;     } else  {         return  "未知类型" ;     } } public  String getDescription (Object obj)  {    if  (obj instanceof  String s) {         return  "字符串,长度: "  + s.length();     } else  if  (obj instanceof  Integer i) {         return  "整数: "  + i;     } else  {         return  "未知类型" ;     } } public  void  processShape (Object obj)  {    if  (obj instanceof  Rectangle r) {         System.out.println("矩形面积: "  + r.area());     } else  if  (obj instanceof  Circle c && c.area() > 100 ) {         System.out.println("大型圆形,面积: "  + c.area());     } } 
 
4. Switch表达式增强 Java 17继承了Java 14引入的Switch表达式,与模式匹配结合使用更加强大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public  String getTypeDescription (Object obj)  {    return  switch  (obj) {         case  String s -> "字符串,内容: "  + s;         case  Integer i -> "整数: "  + i;         case  Long l -> "长整型: "  + l;         case  Double d -> "双精度: "  + d;         case  null  -> "空值" ;         default  -> "其他类型" ;     }; } public  String analyzePerson (Person person)  {    return  switch  (person) {         case  Person p when p.age() < 18  -> p.name() + " 是未成年人" ;         case  Person p when p.age() >= 18  && p.age() < 65  -> p.name() + " 是成年人" ;         case  Person p -> p.name() + " 是老年人" ;     }; } 
 
5. 文本块(Text Blocks) 文本块提供了更好的多行字符串表示方式,特别适合SQL、HTML等内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public  class  TextBlocksExample  {    public  static  void  main (String[] args)  {                  String  oldHtml  =  "<html>\n"  +                          "    <body>\n"  +                          "        <p>Hello, World!</p>\n"  +                          "    </body>\n"  +                          "</html>" ;                                            String  html  =  """                  <html>                     <body>                         <p>Hello, World!</p>                     </body>                 </html>                 """ ;                                  String  query  =  """                  SELECT id, name, email                 FROM users                 WHERE status = 'active'                   AND last_login > DATE_SUB(NOW(), INTERVAL 30 DAY)                 ORDER BY name ASC                 """ ;                                  String  json  =  """                  {                     "name": "张三",                     "age": 30,                     "address": {                         "city": "北京",                         "district": "海淀"                     },                     "skills": ["Java", "Spring", "Kubernetes"]                 }                 """ ;    } } 
 
6. 新的随机数生成器API Java 17引入了强大的随机数生成器API,提供了更多算法选择和更好的性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import  java.util.random.RandomGenerator;import  java.util.random.RandomGeneratorFactory;  public  class  RandomGeneratorExample  {    public  static  void  main (String[] args)  {                  RandomGenerator  defaultRandom  =  RandomGenerator.getDefault();                  System.out.println("随机整数: "  + defaultRandom.nextInt(100 ));                  RandomGenerator  xoroshiro  =  RandomGeneratorFactory.of("Xoroshiro128PlusPlus" )                                                         .create(42 );                   xoroshiro.ints(10 , 1 , 100 )                  .forEach(n -> System.out.print(n + " " ));                  System.out.println("\n可用随机数生成器算法:" );         RandomGeneratorFactory.all()                 .map(factory -> factory.name())                 .sorted()                 .forEach(System.out::println);     } } 
 
7. 强封装JDK内部API Java 17进一步强化了JDK内部API的封装,这需要开发者更加关注公共API的使用。
1 2 3 4 5 6 7 8 9 try  {         Class<?> sunClass = Class.forName("sun.misc.Unsafe" );      } catch  (ClassNotFoundException | IllegalAccessException e) {     System.out.println("无法访问内部API: "  + e.getMessage());      } 
 
8. 实际业务应用案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 public  sealed  interface  Product  permits Electronics, Clothing, Book {    String getId () ;     String getName () ;     double  getPrice () ; } public  record  Electronics (String id, String name, double  price,                           String brand, int  warrantyMonths)  implements  Product  {}                       public  record  Clothing (String id, String name, double  price,                        String size, String material)  implements  Product  {}                  public  record  Book (String id, String name, double  price,                    String author, String isbn)  implements  Product  {}  public  class  ProductProcessor  {    public  String generateProductDescription (Product product)  {         return  switch  (product) {             case  Electronics e -> String.format("%s - %s, 保修期: %d个月" ,                                 e.name(), e.brand(), e.warrantyMonths());             case  Clothing c -> String.format("%s - 尺码: %s, 材质: %s" ,                                 c.name(), c.size(), c.material());             case  Book b -> String.format("%s - 作者: %s, ISBN: %s" ,                                 b.name(), b.author(), b.isbn());         };     }     public  double  calculateTax (Product product)  {         return  switch  (product) {             case  Electronics e when e.price() > 10000  -> e.price() * 0.2 ;             case  Electronics e -> e.price() * 0.15 ;             case  Clothing c -> c.price() * 0.1 ;             case  Book b -> b.price() * 0.05 ;         };     } }   public  class  ShoppingCart  {    private  final  List<Product> items = new  ArrayList <>();          public  void  addItem (Product product)  {         items.add(product);     }     public  double  calculateTotal ()  {         return  items.stream().mapToDouble(Product::getPrice).sum();     }     public  double  calculateTotalWithTax ()  {         ProductProcessor  processor  =  new  ProductProcessor ();         return  items.stream().mapToDouble(p -> p.getPrice() + processor.calculateTax(p)).sum();     }     public  String getReceipt ()  {         ProductProcessor  processor  =  new  ProductProcessor ();         StringBuilder  builder  =  new  StringBuilder ();         builder.append("""                  ===== 购物小票 =====                 日期: %s                 商品列表:                 """ .formatted(LocalDate.now()));             items.forEach(item ->              builder.append("- %s: %.2f 元 (税: %.2f 元)\n"                             .formatted(item.getName(), item.getPrice(), processor.calculateTax(item)))         );         builder.append("""                  ----------------                 总计: %.2f 元                 含税总价: %.2f 元                 ================                 """ .formatted(calculateTotal(), calculateTotalWithTax()));           return  builder.toString();     } } public  class  ProductSystemDemo  {    public  static  void  main (String[] args)  {                  Product  laptop  =  new  Electronics ("E001" , "MacBook Pro" , 12999.0 , "Apple" , 24 );         Product  tshirt  =  new  Clothing ("C001" , "纯棉T恤" , 199.0 , "XL" , "棉" );         Product  javaBook  =  new  Book ("B001" , "Java编程思想" , 108.0 , "Bruce Eckel" , "978-7111213826" );                  ShoppingCart  cart  =  new  ShoppingCart ();         cart.addItem(laptop);         cart.addItem(tshirt);         cart.addItem(javaBook);                  System.out.println(cart.getReceipt());                  Product  randomProduct  =  getRandomProduct(laptop, tshirt, javaBook);         String  analysisResult  =  switch  (randomProduct) {             case  Electronics e when e.price() > 10000  -> "高端电子产品" ;             case  Electronics e -> "普通电子产品" ;             case  Clothing c when "棉" .equals(c.material()) -> "纯棉服装" ;             case  Clothing c -> "其他材质服装" ;             case  Book b -> "图书类产品" ;         };         System.out.println("随机商品分析: "  + analysisResult);     }     private  static  Product getRandomProduct (Product... products)  {         return  products[RandomGenerator.getDefault().nextInt(products.length)];     } }                        
 
9. 总结 Java 17的新特性为开发者提供了更多优雅高效的编程工具:
密封类 :增强了类型系统,提供了更好的封装性和编译时安全性 
记录类 :极大简化了数据传输对象的编写 
**模式匹配for instanceof**:简化了类型检查和转换操作 
Switch表达式增强 :使分支逻辑更简洁清晰 
文本块 :大幅改进了多行字符串的处理 
新的随机数API :提供了更丰富的随机数生成工具 
强封装JDK内部API :鼓励使用公共API,提高代码稳定性 
 
这些新特性不仅提高了代码的简洁性和可读性,还增强了Java语言的表达能力和安全性。结合实际业务场景使用这些特性,可以编写出更优雅、更健壮的Java应用程序。