【Java新版本特性】【v5 - v21】

管理员
# Java版本新特性全解析:从Java 5到Java 21 > Java的发展历程是一部不断演进的技术史诗。从2004年的Java 5到2023年的Java 21,每个版本都在推动着Java生态向前发展。 --- ## 前言 Java自1995年诞生以来,经历了多个重要版本。本文将系统梳理从Java 5到Java 21(最新LTS版本)的所有重要新特性,帮助你全面了解Java的演进历程。 **版本分类说明**: - **LTS(长期支持)版本**:Java 8, 11, 17, 21 - 生产环境推荐使用 - **非LTS版本**:6个月更新周期,适合尝鲜和学习 --- ## Java 5(代号:Tiger)- 2004年 Java 5是Java历史上最重要的版本之一,引入了大量革命性特性。 ### 核心特性 #### 1. 泛型(Generics) ```java // 泛型集合 List names = new ArrayList(); names.add("Java"); // 泛型方法 public T findFirst(List list) { return list.isEmpty() ? null : list.get(0); } // 泛型类 class Box { private T item; public void set(T item) { this.item = item; } public T get() { return item; } } ``` **意义**:编译时类型检查,避免ClassCastException #### 2. 增强for循环(For-Each Loop) ```java List languages = Arrays.asList("Java", "Python", "Go"); // 传统方式 for (int i = 0; i < languages.size(); i++) { System.out.println(languages.get(i)); } // 增强for循环 for (String lang : languages) { System.out.println(lang); } ``` #### 3. 自动装箱/拆箱(Autoboxing/Unboxing) ```java // 自动装箱 Integer a = 100; // 相当于 Integer.valueOf(100) // 自动拆箱 int b = a; // 相当于 a.intValue() // 集合中使用 List numbers = new ArrayList<>(); numbers.add(10); // 自动装箱 int sum = numbers.get(0); // 自动拆箱 ``` #### 4. 枚举(Enum) ```java public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; // 枚举可以包含方法和字段 private String description; Day() { this.description = "Day of week"; } } // 使用 Day today = Day.MONDAY; switch (today) { case MONDAY: System.out.println("Start of week"); break; } ``` #### 5. 可变参数(Varargs) ```java public void printAll(String... args) { for (String arg : args) { System.out.println(arg); } } // 使用 printAll("Hello", "World", "Java"); printAll("Single argument"); printAll(); // 空参数 ``` #### 6. 静态导入(Static Import) ```java import static java.lang.Math.*; import static java.util.Collections.*; public class Demo { public void test() { double value = sqrt(25.0); // 不需要 Math.sqrt(25.0) List list = new ArrayList<>(); sort(list); // 不需要 Collections.sort(list) } } ``` #### 7. 注解(Annotations) ```java // 自定义注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { String value() default ""; int priority() default 0; } // 使用注解 public class Demo { @MyAnnotation(value = "Important method", priority = 1) public void importantMethod() { System.out.println("This is important!"); } } ``` #### 8. 并发包(java.util.concurrent) ```java // 线程池 ExecutorService executor = Executors.newFixedThreadPool(5); executor.submit(() -> System.out.println("Task executed")); executor.shutdown(); // 并发集合 ConcurrentHashMap map = new ConcurrentHashMap<>(); CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); // 原子类 AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet(); ``` --- ## Java 6(代号:Mustang)- 2006年 Java 6主要关注性能优化和API增强。 ### 核心特性 #### 1. JDBC 4.0 ```java // 无需显式加载驱动 // Class.forName("com.mysql.jdbc.Driver"); // 不再需要 Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/mydb", "user", "password" ); ``` #### 2. StAX(Streaming API for XML) ```java XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("file.xml")); while (reader.hasNext()) { int event = reader.next(); if (event == XMLStreamConstants.START_ELEMENT) { System.out.println("Element: " + reader.getLocalName()); } } ``` #### 3. 脚本引擎支持(JSR 223) ```java ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); engine.eval("print('Hello from JavaScript!')"); Object result = engine.eval("10 + 20"); System.out.println("Result: " + result); ``` #### 4. Compiler API ```java JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Iterable compilationUnits = fileManager.getJavaFileObjectsFromStrings(Arrays.asList("MyClass.java")); compiler.getTask(null, fileManager, null, null, null, compilationUnits).call(); ``` #### 5. 性能优化 - 改进的锁机制 - 更好的垃圾回收器 - 类数据共享(Class Data Sharing) --- ## Java 7(代号:Dolphin)- 2011年 Java 7引入了许多语法糖和实用特性。 ### 核心特性 #### 1. 二进制字面量 ```java int binary = 0b10101010; // 二进制表示 int binary2 = 0B1010_1010; // 支持下划线分隔 int hex = 0x2A; // 十六进制 ``` #### 2. 数字字面量中的下划线 ```java long creditCardNumber = 1234_5678_9012_3456L; long socialSecurityNumber = 999_99_9999L; double pi = 3.141_592_653_589_793d; ``` #### 3. switch语句支持String ```java String day = "MONDAY"; switch (day) { case "MONDAY": System.out.println("Start of week"); break; case "FRIDAY": System.out.println("Almost weekend"); break; default: System.out.println("Mid week"); } ``` #### 4. 泛型实例化类型推断(Diamond Operator) ```java // 旧方式 Map> map = new HashMap>(); // 新方式 - 菱形操作符 Map> map = new HashMap<>(); List list = new ArrayList<>(); ``` #### 5. try-with-resources ```java // 旧方式 BufferedReader br = null; try { br = new BufferedReader(new FileReader("file.txt")); // 读取文件 } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } // 新方式 try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { // 读取文件,资源自动关闭 } catch (IOException e) { e.printStackTrace(); } // 多个资源 try (FileInputStream fis = new FileInputStream("input.txt"); FileOutputStream fos = new FileOutputStream("output.txt")) { // 自动关闭两个资源 } ``` #### 6. 捕获多个异常 ```java // 旧方式 try { // 代码 } catch (IOException e) { handleException(e); } catch (SQLException e) { handleException(e); } // 新方式 try { // 代码 } catch (IOException | SQLException e) { handleException(e); } ``` #### 7. NIO.2(New I/O 2) ```java // Path API Path path = Paths.get("/home/user/documents/file.txt"); Path absolutePath = path.toAbsolutePath(); Path parent = path.getParent(); Path fileName = path.getFileName(); // 文件操作 Files.createFile(Paths.get("newfile.txt")); Files.createDirectory(Paths.get("newdir")); Files.copy(Paths.get("source.txt"), Paths.get("dest.txt")); Files.delete(Paths.get("file.txt")); // 文件遍历 Files.walk(Paths.get("/home/user")) .filter(p -> p.toString().endsWith(".java")) .forEach(System.out::println); // 监控文件系统变化 WatchService watcher = FileSystems.getDefault().newWatchService(); Path dir = Paths.get("/home/user/watch"); dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); ``` #### 8. Fork/Join框架 ```java class Fibonacci extends RecursiveTask { private final int n; public Fibonacci(int n) { this.n = n; } @Override protected Integer compute() { if (n <= 1) { return n; } Fibonacci f1 = new Fibonacci(n - 1); f1.fork(); Fibonacci f2 = new Fibonacci(n - 2); return f2.compute() + f1.join(); } } // 使用 ForkJoinPool pool = new ForkJoinPool(); int result = pool.invoke(new Fibonacci(10)); ``` --- ## Java 8(代号:Spider)- 2014年 ⭐ LTS Java 8是Java历史上最革命性的版本,引入了函数式编程特性。 ### 核心特性 #### 1. Lambda表达式 ```java // 旧方式 - 匿名内部类 Runnable r1 = new Runnable() { @Override public void run() { System.out.println("Hello from anonymous class"); } }; // 新方式 - Lambda表达式 Runnable r2 = () -> System.out.println("Hello from lambda"); // Lambda表达式语法 // 参数 -> 表达式 // (参数) -> { 语句; } // (参数1, 参数2) -> { 语句1; 语句2; } // 函数式接口 @FunctionalInterface interface MathOperation { int operate(int a, int b); } MathOperation addition = (a, b) -> a + b; MathOperation multiplication = (a, b) -> a * b; System.out.println(addition.operate(5, 3)); // 8 ``` #### 2. 方法引用 ```java List names = Arrays.asList("Alice", "Bob", "Charlie"); // 静态方法引用 names.forEach(System.out::println); // 实例方法引用 names.stream() .map(String::toLowerCase) .forEach(System.out::println); // 构造器引用 Supplier> listSupplier = ArrayList::new; List newList = listSupplier.get(); // 特定对象的方法引用 String prefix = "Hello, "; Function addPrefix = prefix::concat; ``` #### 3. Stream API ```java List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 过滤和映射 List evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .map(n -> n * 2) .collect(Collectors.toList()); // 结果: [4, 8, 12, 16, 20] // 求和 int sum = numbers.stream() .reduce(0, Integer::sum); // 分组 Map> grouped = numbers.stream() .collect(Collectors.groupingBy(n -> n % 2 == 0)); // 查找 Optional first = numbers.stream() .filter(n -> n > 5) .findFirst(); // 统计 IntSummaryStatistics stats = numbers.stream() .mapToInt(Integer::intValue) .summaryStatistics(); System.out.println("Max: " + stats.getMax()); System.out.println("Average: " + stats.getAverage()); // 并行流 long count = numbers.parallelStream() .filter(n -> n > 5) .count(); ``` #### 4. Optional类 ```java // 避免NullPointerException Optional optional = Optional.of("Hello"); // 判断是否存在 if (optional.isPresent()) { System.out.println(optional.get()); } // orElse - 提供默认值 String value = optional.orElse("Default Value"); // orElseGet - 延迟提供默认值 String value2 = optional.orElseGet(() -> computeDefault()); // orElseThrow - 为空时抛出异常 String value3 = optional.orElseThrow(() -> new IllegalArgumentException("Value not present")); // map转换 Optional length = optional.map(String::length); // flatMap - 避免嵌套Optional Optional result = optional.flatMap(s -> Optional.of(s.toUpperCase())); // ifPresent - 存在时执行操作 optional.ifPresent(System.out::println); // 创建Optional Optional nonNull = Optional.of("Value"); Optional nullable = Optional.ofNullable(null); // Optional.empty Optional empty = Optional.empty(); ``` #### 5. 新的日期时间API(java.time) ```java // LocalDate - 日期(年月日) LocalDate today = LocalDate.now(); LocalDate birthday = LocalDate.of(1990, Month.JANUARY, 15); LocalDate parsed = LocalDate.parse("2024-03-15"); // LocalTime - 时间(时分秒) LocalTime now = LocalTime.now(); LocalTime specificTime = LocalTime.of(14, 30, 45); LocalTime parsedTime = LocalTime.parse("14:30:45"); // LocalDateTime - 日期时间 LocalDateTime dateTime = LocalDateTime.now(); LocalDateTime specificDateTime = LocalDateTime.of(2024, 3, 15, 14, 30); // ZonedDateTime - 带时区的时间 ZonedDateTime zonedTime = ZonedDateTime.now(); ZonedDateTime parisTime = ZonedDateTime.now(ZoneId.of("Europe/Paris")); // Duration - 时间段 Duration duration = Duration.between(LocalTime.NOON, LocalTime.now()); // Period - 日期段 Period period = Period.between(birthday, today); // DateTimeFormatter - 格式化 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatted = dateTime.format(formatter); // 日期计算 LocalDate nextWeek = today.plusWeeks(1); LocalDate previousMonth = today.minusMonths(1); LocalDate nextYear = today.plusYears(1); // 日期比较 boolean isBefore = birthday.isBefore(today); boolean isAfter = today.isAfter(birthday); // 调整日期 LocalDate firstDayOfMonth = today.withDayOfMonth(1); LocalDate lastDayOfYear = today.withDayOfYear(365); ``` #### 6. 接口默认方法和静态方法 ```java public interface Vehicle { // 抽象方法 String start(); // 默认方法 default void stop() { System.out.println("Vehicle stopped"); } // 静态方法 static void info() { System.out.println("This is a vehicle interface"); } } // 实现类可以选择是否覆盖默认方法 class Car implements Vehicle { @Override public String start() { return "Car started"; } // 使用默认的stop方法 } // 使用 Car car = new Car(); car.start(); // "Car started" car.stop(); // "Vehicle stopped" - 使用默认方法 Vehicle.info(); // "This is a vehicle interface" ``` #### 7. 重复注解 ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Authors { Author[] value(); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Repeatable(Authors.class) public @interface Author { String name(); String email(); } @Author(name = "John", email = "john@example.com") @Author(name = "Jane", email = "jane@example.com") public class MyBook { // 类定义 } // 读取重复注解 Authors authors = MyBook.class.getAnnotation(Authors.class); for (Author author : authors.value()) { System.out.println(author.name() + " - " + author.email()); } ``` #### 8. CompletableFuture ```java // 异步执行 CompletableFuture future = CompletableFuture.supplyAsync(() -> { // 模拟耗时操作 try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "Hello"; }); // thenApply - 转换结果 CompletableFuture lengthFuture = future.thenApply(String::length); // thenAccept - 消费结果 CompletableFuture voidFuture = future.thenAccept(System.out::println); // thenRun - 不依赖结果的后续操作 CompletableFuture runFuture = future.thenRun(() -> System.out.println("Done!")); // 组合多个Future CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture future2 = CompletableFuture.supplyAsync(() -> "World"); CompletableFuture combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2); // 等待结果 String result = combined.get(); // "Hello World" // 异常处理 CompletableFuture futureWithException = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("Something went wrong"); } return "Success"; }).exceptionally(ex -> { System.err.println("Exception: " + ex.getMessage()); return "Default Value"; }); ``` #### 9. Base64编码 ```java import java.util.Base64; String original = "Hello, World!"; // 编码 String encoded = Base64.getEncoder().encodeToString(original.getBytes()); // "SGVsbG8sIFdvcmxkIQ==" // 解码 byte[] decodedBytes = Base64.getDecoder().decode(encoded); String decoded = new String(decodedBytes); // "Hello, World!" // URL编码 String urlEncoded = Base64.getUrlEncoder().withoutPadding() .encodeToString(original.getBytes()); // MIME编码 String mimeEncoded = Base64.getMimeEncoder() .encodeToString(original.getBytes()); ``` #### 10. 并行数组排序 ```java int[] array = {5, 2, 8, 1, 9, 3}; // 串行排序 Arrays.sort(array); // 并行排序 - 适合大数组 Arrays.parallelSort(array); // 并行排序数组的一部分 int[] largeArray = new int[1000000]; Arrays.fill(largeArray, 1); Arrays.parallelSort(largeArray, 0, 500000); // 只排序前50万个元素 ``` --- ## Java 9 - 2017年 Java 9是模块化时代的开始,引入了Jigsaw项目。 ### 核心特性 #### 1. 模块化系统(Jigsaw) ```java // 模块描述文件 module-info.java module com.example.myapp { requires java.base; // 默认依赖 requires java.logging; // 显式依赖 exports com.example.myapp.api; // 导出包 exports com.example.myapp.service to com.example.other; // 限定导出 uses com.example.myapp.spi.Service; // 使用服务 provides com.example.myapp.spi.Service with com.example.myapp.impl.ServiceImpl; // 提供服务 } ``` **模块化命令**: ```bash # 编译模块 javac --module-source-path src -d out --module myapp # 运行模块 java --module-path out --module myapp/com.example.myapp.Main # 列出模块 java --list-modules # 描述模块 java --describe-module java.base ``` #### 2. JShell - Java REPL ```bash # 启动JShell jshell # 执行代码 jshell> int x = 10; x ==> 10 jshell> System.out.println(x * 2); 20 jshell> List list = new ArrayList<>(); list ==> [] jshell> list.add("Java"); $3 ==> true jshell> list [$1 -> "Java"] # 退出 jshell> /exit ``` #### 3. 不可变集合工厂方法 ```java // List.of() - 创建不可变List List immutableList = List.of("Java", "Python", "Go"); immutableList.add("C++"); // UnsupportedOperationException // Set.of() - 创建不可变Set Set immutableSet = Set.of(1, 2, 3, 4, 5); immutableSet.add(6); // UnsupportedOperationException // Map.of() - 创建不可变Map(最多10个键值对) Map map1 = Map.of("Alice", 25, "Bob", 30); // Map.ofEntries() - 创建不可变Map(无键值对数量限制) Map map2 = Map.ofEntries( Map.entry("Alice", 25), Map.entry("Bob", 30), Map.entry("Charlie", 35) ); // 比较旧的Collections.unmodifiableXXX() List oldWay = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("A", "B"))); List newWay = List.of("A", "B"); ``` #### 4. Stream API增强 ```java // takeWhile() - 取满足条件的元素 Stream stream1 = Stream.of(1, 2, 3, 4, 5, 6); stream1.takeWhile(n -> n < 4).forEach(System.out::println); // 1, 2, 3 // dropWhile() - 丢弃满足条件的元素 Stream stream2 = Stream.of(1, 2, 3, 4, 5, 6); stream2.dropWhile(n -> n < 4).forEach(System.out::println); // 4, 5, 6 // ofNullable() - 避免NullPointerException Stream stream3 = Stream.ofNullable("Hello"); // Stream Stream stream4 = Stream.ofNullable(null); // Empty stream // iterate() - 新的重载方法 Stream.iterate(0, n -> n < 10, n -> n + 2).forEach(System.out::println); // 0, 2, 4, 6, 8 ``` #### 5. Optional类增强 ```java // ifPresentOrElse() - 存在和不存在的处理 Optional optional = Optional.of("Java"); optional.ifPresentOrElse( value -> System.out.println("Value: " + value), () -> System.out.println("Value not present") ); // or() - 提供Supplier作为后备 Optional result = optional.or(() -> Optional.of("Default")); // stream() - 转换为Stream optional.stream().forEach(System.out::println); ``` #### 6. 响应式流(Reactive Streams) ```java import java.util.concurrent.Flow; import java.util.concurrent.SubmissionPublisher; // 发布者 SubmissionPublisher publisher = new SubmissionPublisher<>(); // 订阅者 Flow.Subscriber subscriber = new Flow.Subscriber<>() { private Flow.Subscription subscription; @Override public void onSubscribe(Flow.Subscription subscription) { this.subscription = subscription; subscription.request(1); // 请求一个元素 } @Override public void onNext(String item) { System.out.println("Received: " + item); subscription.request(1); // 请求下一个元素 } @Override public void onError(Throwable throwable) { System.err.println("Error: " + throwable.getMessage()); } @Override public void onComplete() { System.out.println("Completed"); } }; // 订阅 publisher.subscribe(subscriber); // 发布消息 publisher.submit("Hello"); publisher.submit("World"); publisher.close(); ``` #### 7. 私有接口方法 ```java public interface MyInterface { default void method1() { commonMethod(); System.out.println("Method 1"); } default void method2() { commonMethod(); System.out.println("Method 2"); } // 私有方法 - 只能在接口内部使用 private void commonMethod() { System.out.println("Common logic"); } // 私有静态方法 private static void staticHelper() { System.out.println("Static helper"); } } ``` #### 8. Process API ```java // 获取当前进程 ProcessHandle currentProcess = ProcessHandle.current(); System.out.println("PID: " + currentProcess.pid()); System.out.println("Command: " + currentProcess.info().command().orElse("N/A")); // 获取所有进程 ProcessHandle.allProcesses() .filter(ph -> ph.info().command().map(c -> c.contains("java")).orElse(false)) .forEach(ph -> System.out.println(ph.pid())); // 启动新进程 ProcessBuilder pb = new ProcessBuilder("notepad.exe"); Process process = pb.start(); ProcessHandle processHandle = process.toHandle(); processHandle.onExit().thenRun(() -> System.out.println("Process exited")); ``` #### 9. 变量句柄(VarHandle) ```java import java.lang.invoke.VarHandle; class MyClass { private volatile int value = 0; private static final VarHandle VALUE_HANDLE; static { try { VALUE_HANDLE = MethodHandles.lookup() .findVarHandle(MyClass.class, "value", int.class); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } } public void setValue(int newValue) { VALUE_HANDLE.setVolatile(this, newValue); } public int getValue() { return (int) VALUE_HANDLE.getVolatile(this); } } ``` #### 10. HTTP/2客户端 ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; // HTTP客户端(Java 9时还是incubator) HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com/data")) .GET() .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); ``` --- ## Java 10 - 2018年 Java 10是一个小版本,主要聚焦于性能改进和局部变量类型推断。 ### 核心特性 #### 1. 局部变量类型推断(var) ```java // 基本用法 var name = "Java"; // 推断为 String var age = 25; // 推断为 int var list = new ArrayList(); // 推断为 ArrayList var map = Map.of("key", "value"); // 推断为 Map // 在循环中使用 for (var item : list) { System.out.println(item); } // 在try-with-resources中使用 try (var reader = new BufferedReader(new FileReader("file.txt"))) { // reader推断为BufferedReader } // 在Lambda中作为返回类型 Supplier> supplier = () -> { var result = new HashMap(); result.put("One", 1); return result; }; // 注意事项 var x; // 编译错误 - 必须初始化 var y = null; // 编译错误 - 不能推断为null var z = {1, 2, 3}; // 编译错误 - 数组初始化器不能使用var // 局部变量类型推断的限制 // 不能用于类成员变量 // 不能用于方法参数 // 不能用于catch块参数 // 不能用于方法返回类型 ``` #### 2. 基于时间的版本控制 Java 10开始采用基于时间的版本号格式: ``` $FEATURE.$INTERIM.$UPDATE.$PATCH 示例:10.0.1.10 - 10:特性版本 - 0:中间版本(非LTS版本为0,LTS版本可能不为0) - 1:更新版本(每6个月递增) - 10:补丁版本(紧急安全修复) ``` #### 3. G1垃圾回收器并行Full GC ```java // 在Java 10之前,G1的Full GC是单线程的 // Java 10改进为并行Full GC,显著提升性能 // 启用G1 GC(JVM参数) java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 MyApp ``` #### 4. ThreadLocal握手 ```java // Java 10引入了Thread-Local Handshake机制 // 允许在不停止所有线程的情况下对单个线程执行操作 // 示例:在运行时获取线程的局部信息 Thread thread = Thread.currentThread(); // JVM内部可以暂停单个线程进行操作 ``` #### 5. 应用程序类数据共享(AppCDS) ```java // 应用程序类数据共享(Application Class-Data Sharing) // 允许在多个JVM进程之间共享类元数据 // 步骤1:创建类列表 java -Xshare:dump -XX:DumpLoadedClassList=classes.lst -XX:SharedArchiveFile=app.jsa MyApp // 步骤2:创建共享归档 java -Xshare:dump -XX:SharedClassListFile=classes.lst -XX:SharedArchiveFile=app.jsa MyApp // 步骤3:使用共享归档启动应用 java -Xshare:on -XX:SharedArchiveFile=app.jsa MyApp ``` #### 6. Heap上的并行分配 ```java // Java 10优化了堆上的并行分配 // 提高了多线程创建对象时的性能 ``` #### 7. Optional类新增方法 ```java // orElseThrow() - 无参数版本 Optional optional = Optional.ofNullable(getValue()); String value = optional.orElseThrow(); // 无参时抛出NoSuchElementException ``` #### 8. 字符串新方法 ```java String text = " Hello World "; // strip() - 去除首尾空白(Unicode空白) String stripped = text.strip(); // "Hello World" // stripLeading() - 去除首部空白 String leading = text.stripLeading(); // "Hello World " // stripTrailing() - 去除尾部空白 String trailing = text.stripTrailing(); // Hello World" // isBlank() - 判断是否为空白字符串 boolean blank = " ".isBlank(); // true // lines() - 按行分割 String multiline = "Line1\nLine2\nLine3"; Stream lines = multiline.lines(); // ["Line1", "Line2", "Line3"] // repeat() - 重复字符串 String repeated = "Java".repeat(3); // "JavaJavaJava" ``` #### 9. 集合新增方法 ```java // List.copyOf() - 创建不可变副本 List original = Arrays.asList("A", "B", "C"); List copy = List.copyOf(original); // Set.copyOf() Set set = Set.copyOf(Arrays.asList(1, 2, 3)); // Map.copyOf() Map map = Map.copyOf(Map.of("key", 1)); // toArray() - 新的重载方法 List list = Arrays.asList("Java", "Python", "Go"); String[] array1 = list.toArray(String[]::new); // 类型推断 // 收集器改进 List names = Stream.of("Alice", "Bob", "Charlie") .collect(Collectors.toUnmodifiableList()); ``` --- ## Java 11(LTS)- 2018年 ⭐ Java 11是继Java 8之后的第二个LTS版本,提供了许多实用改进。 ### 核心特性 #### 1. HTTP客户端标准化 ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; // 创建HTTP客户端 HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) // HTTP/2 .connectTimeout(Duration.ofSeconds(10)) .build(); // GET请求 HttpRequest getRequest = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com/data")) .GET() .build(); HttpResponse getResponse = client.send(getRequest, HttpResponse.BodyHandlers.ofString()); System.out.println("Status: " + getResponse.statusCode()); System.out.println("Body: " + getResponse.body()); // POST请求 - JSON 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(); HttpResponse postResponse = client.send(postRequest, HttpResponse.BodyHandlers.ofString()); // 异步请求 CompletableFuture> asyncResponse = client.sendAsync( getRequest, HttpResponse.BodyHandlers.ofString() ); asyncResponse.thenApply(HttpResponse::body) .thenAccept(System.out::println) .join(); // 上传文件 HttpRequest fileUpload = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com/upload")) .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("file.txt"))) .build(); // 响应体处理器 HttpResponse fileResponse = client.send( getRequest, HttpResponse.BodyHandlers.ofFile(Paths.get("response.txt")) ); // 流式响应 HttpResponse> streamResponse = client.send( getRequest, HttpResponse.BodyHandlers.ofLines() ); streamResponse.body().forEach(System.out::println); ``` #### 2. 字符串新方法 ```java // isBlank() - 判断字符串是否为空白 "".isBlank(); // true " ".isBlank(); // true " hello ".isBlank(); // false // strip() - 去除首尾空白 " hello ".strip(); // "hello" "\u2000hello\u2000".strip(); // "hello" (支持Unicode空白) // stripLeading() - 去除首部空白 " hello ".stripLeading(); // "hello " // stripTrailing() - 去除尾部空白 " hello ".stripTrailing(); // " hello" // lines() - 按行分割 String multiline = "Line1\nLine2\r\nLine3"; Stream lines = multiline.lines(); // ["Line1", "Line2", "Line3"] // repeat() - 重复字符串 "Java".repeat(3); // "JavaJavaJava" "Hi".repeat(0); // "" // stripIndent() - 去除缩进 String indented = """ Line 1 Line 2 Line 3 """; String unindented = indented.stripIndent(); // translateEscapes() - 转义字符处理 String escaped = "Line1\\nLine2\\tTab"; String translated = escaped.translateEscapes(); // "Line1\nLine2\tTab" // formatted() - 字符串格式化 String name = "John"; int age = 30; String result = "Name: %s, Age: %d".formatted(name, age); // "Name: John, Age: 30" ``` #### 3. 局部变量类型推断增强 ```java // Lambda参数可以使用var Consumer consumer = (var s) -> System.out.println(s); // 多个参数都使用var BiFunction concat = (var s1, var s2) -> s1 + s2; // 混合使用(不推荐) BiFunction func = (String s, var i) -> s + i; // 在注解中使用 Consumer<@NotNull String> annotated = (var s) -> process(s); ``` #### 4. 嵌套类访问控制改进 ```java // Java 11之前,私有嵌套类之间不能互相访问私有成员 // Java 11允许私有嵌套类之间互相访问私有成员 public class Outer { private class Inner { private String privateMethod() { return "Private"; } private class InnerInner { public void call() { Inner inner = new Inner(); // 现在可以访问私有方法 String result = inner.privateMethod(); // Java 11允许 } } } } ``` #### 5. Epsilon垃圾回收器(实验性) ```java // Epsilon GC是一个无操作的垃圾回收器 // 用于性能测试、短生命周期应用、内存压力测试 // 启动参数 java -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC MyApp // 特点: // - 不进行任何垃圾回收 // - 当堆满时JVM会退出 // - 适用于已经确定不会产生垃圾的应用 ``` #### 6. ZGC垃圾回收器(实验性) ```java // ZGC(Z Garbage Collector)是一个低延迟的垃圾回收器 // 目标:停顿时间不超过10ms // 启动参数 java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC MyApp // 特点: // - 并发处理 // - 停顿时间极短(通常<10ms) // - 支持TB级堆内存 // - 适用于对延迟敏感的应用 ``` #### 7. Flight Recorder(JFR) ```java // Java Flight Recorder是一个轻量级的性能分析工具 // 现在包含在OpenJDK中 // 启动应用并开启JFR java -XX:StartFlightRecording=duration=60s,filename=recording.jfr MyApp // 程序中控制JFR import jdk.jfr.*; import jdk.jfr.consumer.*; // 创建事件 @Name("com.example.MyEvent") @Label("My Event") public class MyEvent extends Event { @Label("Message") public String message; } // 记录事件 MyEvent event = new MyEvent(); event.message = "Hello"; event.commit(); // 读取记录 RecordingFile recording = new RecordingFile(Paths.get("recording.jfr")); while (recording.hasMoreEvents()) { RecordedEvent recordedEvent = recording.readEvent(); System.out.println(recordedEvent); } ``` #### 8. 单文件源代码程序 ```java // 可以直接运行单个Java文件,无需先编译 // 文件:HelloWorld.java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } // 直接运行 java HelloWorld.java // 支持命令行参数 java HelloWorld.java arg1 arg2 // 支持Shebang(Unix/Linux) #!/usr/bin/java --source 11 public class Script { public static void main(String[] args) { System.out.println("Running as script"); } } ``` #### 9. 废弃Nashorn JavaScript引擎 ```java // Nashorn JavaScript引擎被标记为废弃 // 建议使用其他JavaScript引擎或GraalVM // 旧方式(已废弃) ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); // 替代方案: // 1. 使用GraalVM的JavaScript引擎 // 2. 使用外部JavaScript引擎 ``` #### 10. 集合增强 ```java // Collection.toArray(IntFunction generator) List list = Arrays.asList("A", "B", "C"); String[] array = list.toArray(String[]::new); // Predicate.not() List names = Arrays.asList("Alice", "Bob", "Charlie", null); // 旧方式 List filtered = names.stream() .filter(s -> s != null) .collect(Collectors.toList()); // 新方式 List filtered2 = names.stream() .filter(Objects::nonNull) .collect(Collectors.toList()); // 使用Predicate.not() List longNames = names.stream() .filter(Objects::nonNull) .filter(Predicate.not(s -> s.length() < 5)) .collect(Collectors.toList()); ``` --- ## Java 12 - 2019年 Java 12是一个小版本,引入了一些实用改进。 ### 核心特性 #### 1. Shenandoah垃圾回收器(实验性) ```java // Shenandoah是一个低延迟的垃圾回收器 // 与ZGC类似,但实现方式不同 // 启动参数 java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC MyApp // 特点: // - 并发压缩 // - 停顿时间短(通常<10ms) // - 支持大堆内存 ``` #### 2. switch表达式(预览) ```java // Java 12引入了switch表达式(预览特性) // 旧方式 int day = 3; String dayName; switch (day) { case 1: dayName = "Monday"; break; case 2: dayName = "Tuesday"; break; case 3: dayName = "Wednesday"; break; default: dayName = "Unknown"; } // 新方式 - switch表达式 String dayName = switch (day) { case 1 -> "Monday"; case 2 -> "Tuesday"; case 3 -> "Wednesday"; default -> "Unknown"; }; // 多个case合并 String type = switch (day) { case 1, 2, 3, 4, 5 -> "Weekday"; case 6, 7 -> "Weekend"; default -> "Invalid"; }; // 需要复杂逻辑时使用yield String message = switch (day) { case 1 -> { System.out.println("Start of week"); yield "Monday"; } case 2, 3, 4, 5 -> { System.out.println("Mid week"); yield "Weekday"; } default -> { System.out.println("Weekend"); yield "Weekend"; } }; ``` #### 3. String新方法 ```java // indent() - 缩进处理 String text = "Hello\nWorld\nJava"; String indented = text.indent(4); /* Hello World Java */ String unindented = text.indent(-2); // transform() - 字符串转换 String result = "hello".transform(String::toUpperCase); // "HELLO" // 提取缩进 String withIndent = " Line 1\n Line 2"; String firstLineIndent = withIndent.lines() .findFirst() .orElse("") .indent(0); // 返回第一个非空白行的缩进 ``` #### 4. Files.mismatch() ```java // 比较两个文件内容,返回第一个不匹配字节的位置 Path file1 = Paths.get("file1.txt"); Path file2 = Paths.get("file2.txt"); long mismatchPosition = Files.mismatch(file1, file2); if (mismatchPosition == -1) { System.out.println("Files are identical"); } else { System.out.println("First mismatch at position: " + mismatchPosition); } ``` #### 5. Compact Number Format ```java // 紧凑数字格式化 NumberFormat compactFormat = NumberFormat.getCompactNumberInstance( Locale.US, NumberFormat.Style.SHORT ); System.out.println(compactFormat.format(1000)); // "1K" System.out.println(compactFormat.format(1000000)); // "1M" System.out.println(compactFormat.format(1500)); // "2K"(向上取整) // 长格式 NumberFormat longFormat = NumberFormat.getCompactNumberInstance( Locale.US, NumberFormat.Style.LONG ); System.out.println(longFormat.format(1000)); // "1 thousand" System.out.println(longFormat.format(1000000)); // "1 million" ``` #### 6. Collector.teeing() ```java // teeing() - 两个收集器的组合 List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 同时计算最小值和最大值 MinMax minMax = numbers.stream() .collect(Collectors.teeing( Collectors.minBy(Integer::compare), Collectors.maxBy(Integer::compare), (min, max) -> new MinMax(min.orElse(null), max.orElse(null)) )); class MinMax { Integer min; Integer max; public MinMax(Integer min, Integer max) { this.min = min; this.max = max; } @Override public String toString() { return "Min: " + min + ", Max: " + max; } } // 同时计算总和和数量 SumCount sumCount = numbers.stream() .collect(Collectors.teeing( Collectors.summingInt(Integer::intValue), Collectors.counting(), (sum, count) -> new SumCount(sum, count) )); ``` --- ## Java 13 - 2019年 Java 13继续改进语言特性和JVM。 ### 核心特性 #### 1. 文本块(预览) ```java // 旧方式 - 字符串拼接需要大量转义 String json = "{\n" + " \"name\": \"John\",\n" + " \"age\": 30,\n" + " \"city\": \"New York\"\n" + "}"; String html = "\n" + " \n" + "

Hello, World!

\n" + " \n" + ""; // 新方式 - 文本块(Java 13预览) String json = """ { "name": "John", "age": 30, "city": "New York" } """; String html = """

Hello, World!

"""; // SQL查询 String sql = """ SELECT id, name, email FROM users WHERE status = 'active' ORDER BY name """; // 正则表达式 String regex = """ ^ # 行首 [A-Za-z]+ # 字母 \\s+ # 空白字符 \\d{3,5} # 3-5位数字 $ # 行尾 """; ``` #### 2. switch表达式增强(预览) ```java // Java 13改进了yield关键字的使用 String message = switch (day) { case 1 -> "Monday"; case 2 -> "Tuesday"; case 3 -> { System.out.println("Mid week day"); yield "Wednesday"; // 使用yield返回值 } default -> "Unknown"; }; // 多个值 String type = switch (day) { case 1, 2, 3, 4, 5 -> "Weekday"; case 6, 7 -> "Weekend"; default -> "Invalid"; }; ``` #### 3. Socket API重构 ```java // Java 13重构了底层Socket API // 从java.net.SocketImpl改为NIO实现 // 性能提升,更易于维护 // 使用方式不变 Socket socket = new Socket("example.com", 80); ServerSocket serverSocket = new ServerSocket(8080); ``` #### 4. FileSystems.newFileSystem() ```java // 简化文件系统创建 Path zipPath = Paths.get("archive.zip"); FileSystem fs = FileSystems.newFileSystem(zipPath); // 访问ZIP文件中的内容 Path fileInZip = fs.getPath("file.txt"); Files.readAllLines(fileInZip).forEach(System.out::println); ``` #### 5. 动态CDS归档 ```java // 动态类数据共享归档 // 允许在应用运行时创建CDS归档 // 步骤1:运行应用并记录类 java -Xshare:off -XX:DumpLoadedClassList=classes.lst MyApp // 步骤2:创建CDS归档 java -Xshare:dump -XX:SharedClassListFile=classes.lst -XX:SharedArchiveFile=app.jsa // 步骤3:使用CDS归档运行应用 java -Xshare:on -XX:SharedArchiveFile=app.jsa MyApp // Java 13改进:可以在运行时创建归档 java -XX:ArchiveClassesAtExit=app.jsa MyApp ``` --- ## Java 14 - 2020年 Java 14引入了记录类型和模式匹配等重要特性。 ### 核心特性 #### 1. 记录类型(Records - 预览) ```java // 记录类型 - 不可变的数据载体 public record Person(String name, int age) { // 自动生成构造方法、getter、equals、hashCode、toString } // 使用 Person person = new Person("Alice", 30); System.out.println(person.name()); // Alice System.out.println(person.age()); // 30 System.out.println(person); // Person[name=Alice, age=30] Person person2 = new Person("Alice", 30); System.out.println(person.equals(person2)); // true // 带验证的记录 public record Employee(String name, int age, double salary) { public Employee { if (age < 18) { throw new IllegalArgumentException("Age must be at least 18"); } if (salary < 0) { throw new IllegalArgumentException("Salary cannot be negative"); } } } // 带额外方法的记录 public record Product(String id, String name, double price) { public double getPriceWithTax(double taxRate) { return price * (1 + taxRate); } public String getFormattedPrice() { return String.format("$%.2f", price); } } ``` #### 2. instanceof模式匹配(预览) ```java // 旧方式 Object obj = "Hello World"; if (obj instanceof String) { String str = (String) obj; System.out.println(str.length()); } // 新方式 - 模式匹配 Object obj = "Hello World"; if (obj instanceof String str) { // 自动转换 System.out.println(str.length()); // 直接使用str,无需强转 } // 结合条件 if (obj instanceof String str && str.length() > 5) { System.out.println("Long string: " + str); } // 不支持或运算 // if (obj instanceof String str || obj instanceof Integer i) // 编译错误 ``` #### 3. 有用的NullPointerException ```java // Java 14改进了NullPointerException的错误信息 // 明确指出哪个对象为null // 代码 Person person = new Person(null, 30); System.out.println(person.name().length()); // 旧错误信息 // Exception in thread "main" java.lang.NullPointerException // 新错误信息(Java 14) // Exception in thread "main" java.lang.NullPointerException: // Cannot invoke "String.length()" because the return value of "Person.name()" is null // 链式调用 person.address().city().length(); // 详细错误信息 // Exception in thread "main" java.lang.NullPointerException: // Cannot invoke "String.length()" because "person.address().city()" is null ``` #### 4. switch表达式(正式) ```java // switch表达式在Java 14正式发布 String result = switch (day) { case 1 -> "Monday"; case 2 -> "Tuesday"; case 3 -> "Wednesday"; case 4 -> "Thursday"; case 5 -> "Friday"; case 6 -> "Saturday"; case 7 -> "Sunday"; default -> "Unknown"; }; // 需要复杂逻辑时使用yield String message = switch (day) { case 1 -> { System.out.println("Start of week"); yield "Monday"; } case 2, 3, 4, 5 -> "Weekday"; case 6, 7 -> { System.out.println("Weekend"); yield "Weekend"; } default -> throw new IllegalArgumentException("Invalid day: " + day); }; ``` #### 5. 打包工具(jpackage) ```java // jpackage工具用于打包Java应用为原生安装包 // 支持Windows、macOS、Linux // 命令行使用 jpackage --name MyApp \ --input ./build/libs \ --main-jar myapp.jar \ --main-class com.example.Main \ --type dmg // 输出类型: // Windows: exe, msi // macOS: dmg, pkg // Linux: deb, rpm // 创建可执行文件 jpackage --name MyApp \ --main-jar myapp.jar \ --main-class com.example.Main \ --type app-image // 应用程序图标 jpackage --name MyApp \ --icon myapp.ico \ --main-jar myapp.jar \ --main-class com.example.Main ``` #### 6. JFR事件流 ```java // JFR(Java Flight Recorder)支持持续的事件流 import jdk.jfr.*; import jdk.jfr.consumer.*; // 创建RecordingStream try (RecordingStream rs = new RecordingStream()) { // 监听CPU使用 rs.enable("jdk.CPUUsage").withPeriod(Duration.ofSeconds(1)); // 监听方法进入 rs.enable("jdk.MethodEnter").withPeriod(Duration.ofMillis(100)); // 处理事件 rs.onEvent("jdk.CPUUsage", event -> { System.out.println("CPU Usage: " + event.getFloat("user")); }); rs.start(); } ``` #### 7. G1 NUMA感知内存分配 ```java // G1垃圾回收器现在对NUMA(非统一内存访问)架构更友好 // 多核处理器可以更高效地访问本地内存 // 启用NUMA感知 java -XX:+UseG1GC -XX:+UseNUMA MyApp ``` --- ## Java 15 - 2020年 Java 15进一步完善了预览特性并引入了新特性。 ### 核心特性 #### 1. 文本块(正式) ```java // 文本块在Java 15正式发布 // 三个双引号"""开始和结束 // JSON String json = """ { "name": "John", "age": 30, "address": { "city": "New York", "country": "USA" } } """; // HTML String html = """ My Page

Hello, World!

"""; // 多行字符串 String message = """ Dear User, Thank you for using our service. Your account has been activated. Best regards, The Team """; // 避免转义 String path = "C:\\Users\\John\\Documents\\file.txt"; // 旧方式 String path = """C:\Users\John\Documents\file.txt"""; // 新方式 // 字符串连接 String sql = """ SELECT id, name, email FROM users WHERE status = 'active' ORDER BY name """; // 文本块中的格式化 String formatted = """ Name: %s Age: %d City: %s """.formatted("Alice", 30, "New York"); ``` #### 2. 密封类(Sealed Classes - 预览) ```java // 密封类 - 限制哪些类可以继承或实现 public sealed interface Shape permits Circle, Rectangle, Triangle { double area(); double perimeter(); } // 允许的子类 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; } @Override public double perimeter() { return 2 * Math.PI * 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; } @Override public double perimeter() { return 2 * (width + height); } } // 密封类的子类必须是final、sealed或non-sealed public non-sealed class Triangle implements Shape { // non-sealed允许进一步继承 } // 记录类型也可以是密封的 public sealed record Point(int x, int y) permits ColoredPoint { } public final record ColoredPoint(int x, int y, String color) extends Point { } ``` #### 3. 隐藏类(Hidden Classes) ```java // 隐藏类 - 不能被其他类直接引用的类 // 用于动态生成代码的场景(如Lambda、反射) import java.lang.invoke.*; import java.lang.reflect.*; // 定义隐藏类 byte[] bytecode = loadBytecode(); // 加载字节码 MethodHandles.Lookup lookup = MethodHandles.lookup(); Class hiddenClass = lookup.defineHiddenClass(bytecode, true).lookupClass(); // 创建实例 Object instance = hiddenClass.getDeclaredConstructor().newInstance(); // 调用方法 Method method = hiddenClass.getMethod("hello"); method.invoke(instance); // 调用hello()方法 // 隐藏类特点: // - 不在类加载器的命名空间中 // - 不能被反射发现 // - 适用于动态代理、字节码生成等场景 ``` #### 4. 模式匹配instanceof(第二轮预览) ```java // instanceof模式匹配第二轮预览 Object obj = getSomeObject(); // 简化类型检查和转换 if (obj instanceof String str) { System.out.println(str.toUpperCase()); } // 在条件中使用 if (obj instanceof String str && str.length() > 10) { System.out.println("Long string: " + str); } // 在循环中使用 List list = Arrays.asList("Hello", 123, "World", true); for (Object item : list) { if (item instanceof String str) { System.out.println("String: " + str); } } ``` #### 5. 记录类型(Records - 第二轮预览) ```java // 记录类型第二轮预览 public record Point(int x, int y) { // 紧凑构造方法 public Point { if (x < 0 || y < 0) { throw new IllegalArgumentException("Coordinates must be non-negative"); } } } // 带自定义方法的记录 public record Person(String name, int age) { public String getGreeting() { return "Hello, I'm " + name + ", " + age + " years old"; } // 静态方法 public static Person of(String name, int age) { return new Person(name, age); } } // 嵌套记录 public record Address(String street, String city, String zipCode) { } public record Employee(String name, int age, Address address) { } ``` #### 6. 移除Nashorn JavaScript引擎 ```java // Nashorn JavaScript引擎在Java 15中完全移除 // 不再可用 // 替代方案: // 1. 使用GraalVM JavaScript引擎 // 2. 使用外部JavaScript引擎 // 3. 使用REST API与JavaScript后端通信 ``` #### 7. ZGC垃圾回收器改进 ```java // ZGC现在支持平台上的所有操作系统和架构 // 不再需要实验性标志 // 启动ZGC java -XX:+UseZGC MyApp // ZGC特性: // - 停顿时间<10ms // - 支持TB级堆内存 // - 适用于大内存应用 ``` --- ## Java 16 - 2021年 Java 16带来了许多实用特性和性能改进。 ### 核心特性 #### 1. 记录类型(Records - 正式) ```java // 记录类型在Java 16正式发布 // 用于创建不可变数据载体 // 基本记录 public record User(String username, String email, int age) { } // 使用 User user = new User("john_doe", "john@example.com", 30); System.out.println(user.username()); // john_doe System.out.println(user); // User[username=john_doe, email=john@example.com, age=30] // 带验证的记录 public record Product(String id, String name, double price) { public Product { if (name == null || name.isBlank()) { throw new IllegalArgumentException("Name cannot be blank"); } if (price < 0) { throw new IllegalArgumentException("Price cannot be negative"); } } } // 带自定义方法的记录 public record Order(String orderId, List items, double total) { public Order { total = items.stream() .mapToDouble(this::getItemPrice) .sum(); } private double getItemPrice(String itemId) { // 从数据库获取价格 return 10.0; // 示例 } public int getItemCount() { return items.size(); } public boolean isExpensive() { return total > 100; } } // 记录与集合 List users = List.of( new User("alice", "alice@example.com", 25), new User("bob", "bob@example.com", 30) ); // 记录作为Map键 Map userRoles = new HashMap<>(); userRoles.put(user, "Admin"); // 记录在Stream中使用 users.stream() .filter(u -> u.age() >= 30) .map(User::username) .forEach(System.out::println); ``` #### 2. instanceof模式匹配(正式) ```java // instanceof模式匹配在Java 16正式发布 Object obj = getSomeObject(); // 简化代码 if (obj instanceof String str && str.length() > 5) { System.out.println("Long string: " + str); } // 在异常处理中使用 try { // some code } catch (Exception e) { if (e instanceof IOException ioe) { System.out.println("IO Error: " + ioe.getMessage()); } else if (e instanceof RuntimeException rte) { System.out.println("Runtime Error: " + rte.getMessage()); } } // 在集合中使用 List mixed = Arrays.asList("Hello", 123, true, "World"); long stringCount = mixed.stream() .filter(o -> o instanceof String) .count(); ``` #### 3. 向量API(孵化) ```java // 向量API用于高性能计算 import jdk.incubator.vector.*; // 创建向量 static final FloatVector.FloatSpecies SPECIES = FloatVector.SPECIES_PREFERRED; // 向量计算示例 public static void vectorComputation(float[] a, float[] b, float[] c) { int i = 0; int upperBound = SPECIES.loopBound(a.length); for (; i < upperBound; i += SPECIES.length()) { FloatVector va = FloatVector.fromArray(SPECIES, a, i); FloatVector vb = FloatVector.fromArray(SPECIES, b, i); FloatVector vc = va.mul(va).add(vb.mul(vb)).neg(); vc.intoArray(c, i); } // 处理剩余元素 for (; i < a.length; i++) { c[i] = -(a[i] * a[i] + b[i] * b[i]); } } // 向量运算可以显著提升数值计算性能 // 特别适合科学计算、图像处理、机器学习等场景 ``` #### 4. Unix域套接字通道 ```java // Unix域套接字用于进程间通信 import java.net.*; import java.nio.channels.*; import java.nio.ByteBuffer; // 创建Unix域套接字服务器 UnixSocketAddress address = new UnixSocketAddress("/tmp/mysocket"); ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX); serverChannel.bind(address); // 接受连接 SocketChannel clientChannel = serverChannel.accept(); // Unix域套接字客户端 SocketChannel client = SocketChannel.open(StandardProtocolFamily.UNIX); client.connect(new UnixSocketAddress("/tmp/mysocket")); // 读写数据 ByteBuffer buffer = ByteBuffer.allocate(1024); client.read(buffer); // Unix域套接字比TCP套接字性能更好 // 适用于本地进程间通信 ``` #### 5. 值类的预览(准备) ```java // Java 16为值类(Value Classes)做准备 // 值类将提供更好的内存布局和性能 // 未来语法(预览特性) public value class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } } // 值类特点: // - 无身份(没有引用相等) // - 内联存储(类似int、double) // - 更好的缓存局部性 // - 更少的内存占用 ``` #### 6. 封装告警 ```java // Java 16开始对反射访问内部API发出警告 // 内部API将被完全封装 // 旧方式 - 访问内部API(已废弃) Class unsafeClass = Class.forName("sun.misc.Unsafe"); Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); // 将来会抛出异常 // InaccessibleObjectException: Unable to make field private static final // sun.misc.Unsafe sun.misc.Unsafe.theUnsafe accessible // 建议使用标准API // 或者通过--add-opens标志临时开放 java --add-opens java.base/sun.misc=ALL-UNNAMED MyApp ``` #### 7. 弹性元空间 ```java // 元空间现在可以更快地将未使用的内存归还给操作系统 // 减少内存占用 // JVM参数 -XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=64m // 弹性元空间特点: // - 更快的内存归还 // - 更好的内存利用率 // - 适合动态类加载场景 ``` --- ## Java 17(LTS)- 2021年 ⭐ Java 17是继Java 11之后的第三个LTS版本。 ### 核心特性 #### 1. 密封类(Sealed Classes - 正式) ```java // 密封类在Java 17正式发布 // 限制继承和实现的类 // 密封接口 public sealed interface Vehicle permits Car, Truck, Motorcycle { void start(); void stop(); } // 允许的实现类 public final class Car implements Vehicle { @Override public void start() { System.out.println("Car started"); } @Override public void stop() { System.out.println("Car stopped"); } } public final class Truck implements Vehicle { @Override public void start() { System.out.println("Truck started"); } @Override public void stop() { System.out.println("Truck stopped"); } } // non-sealed允许进一步继承 public non-sealed class Motorcycle implements Vehicle { @Override public void start() { System.out.println("Motorcycle started"); } @Override public void stop() { System.out.println("Motorcycle stopped"); } } // 非密封子类可以进一步扩展 class ElectricMotorcycle extends Motorcycle { // 可以添加额外功能 } // 密封类 public sealed abstract class Shape permits Circle, Rectangle, Triangle { public abstract double area(); } public final class Circle extends Shape { private final double radius; public Circle(double radius) { this.radius = radius; } @Override public double area() { return Math.PI * radius * radius; } } // 模式匹配与密封类结合 public double getArea(Shape shape) { return switch (shape) { case Circle c -> Math.PI * c.radius() * c.radius(); case Rectangle r -> r.width() * r.height(); case Triangle t -> 0.5 * t.base() * t.height(); }; } ``` #### 2. 增强的伪随机数生成器 ```java // Java 17引入了新的随机数生成器接口 import java.util.random.*; // 使用新的随机数生成器 RandomGenerator random = RandomGenerator.of("L32X64MixRandom"); RandomGeneratorFactory factory = RandomGeneratorFactory.of("L32X64MixRandom"); RandomGenerator generator = factory.create(); // 生成随机数 int randomInt = generator.nextInt(100); double randomDouble = generator.nextDouble(); long randomLong = generator.nextLong(); // 生成随机流 IntStream randomInts = generator.ints(10, 0, 100); DoubleStream randomDoubles = generator.doubles(5); // 可用的随机数生成器算法 // "L32X64MixRandom" - 默认算法,平衡性能和质量 // "Xoroshiro128PlusPlus" - 快速,适合非安全场景 // "Xoshiro256PlusPlus" - 快速,适合并行 // "SecureRandom" - 加密安全 ``` #### 3. 强封装JDK内部API ```java // Java 17强烈封装JDK内部API // 默认情况下无法通过反射访问 // 访问内部API会抛出异常 try { Class unsafeClass = Class.forName("sun.misc.Unsafe"); unsafeClass.getDeclaredField("theUnsafe").setAccessible(true); } catch (InaccessibleObjectException e) { System.err.println("Cannot access internal API: " + e.getMessage()); } // 临时开放内部API(不推荐) java --add-opens java.base/sun.misc=ALL-UNNAMED MyApp // 查看哪些包被打开 java -Xlog:module+exports=info MyApp // 受影响的内部API包括: // - sun.misc.Unsafe // - sun.reflect.Reflection // - sun.security.util // - com.sun.imageio.plugins ``` #### 4. 移除实验性AOT和JIT编译器 ```java // Java 17移除了实验性的AOT和JIT编译器 // - jaotc工具移除 // - Graal相关API移除 // 替代方案: // 1. 使用GraalVM的原生镜像 // 2. 使用C2编译器(默认) // 3. 使用Shenandoah或ZGC // 创建原生镜像(使用GraalVM) native-image --no-fallback MyApp ``` #### 5. 恢复严格浮点语义 ```java // Java 17恢复了严格的浮点语义 // 确保跨平台的一致性 // 浮点运算现在严格遵守IEEE 754标准 double a = 0.1; double b = 0.2; double c = a + b; // 所有平台上结果一致 // 之前可能因硬件优化导致结果不一致 ``` #### 6. 总是严格的浮点语义 ```java // 使用StrictMath类进行严格的浮点运算 import java.math.BigDecimal; // 精确计算 BigDecimal bd1 = new BigDecimal("0.1"); BigDecimal bd2 = new BigDecimal("0.2"); BigDecimal result = bd1.add(bd2); System.out.println(result); // 0.3 // StrictMath保证跨平台一致性 double sinValue = StrictMath.sin(Math.PI / 2); double logValue = StrictMath.log(Math.E); ``` #### 7. Applet API移除 ```java // Applet API在Java 17中完全移除 // 不再支持浏览器中运行的Java Applet // 替代方案: // 1. 使用WebAssembly // 2. 使用JavaScript // 3. 使用现代Web技术 // 4. 使用JavaFX桌面应用 ``` #### 8. Context-specific反序列化过滤器 ```java // 反序列化过滤器防止安全漏洞 import java.io.*; import java.util.function.*; // 定义过滤器 ObjectInputFilter filter = ObjectInputFilter.Config.createFilter( "java.lang.*;!*" ); // 应用过滤器 ObjectInputFilter.Config.setSerialFilter(filter); // 在特定上下文中使用过滤器 try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"))) { ois.setObjectInputFilter(filter); Object obj = ois.readObject(); } // 过滤器规则: // - "java.lang.*" - 允许java.lang包下的所有类 // - "!*" - 拒绝其他所有类 // - 可以组合多个规则 ``` #### 9. macOS/AArch64端口 ```java // Java 17原生支持Apple Silicon(M1/M2芯片) // 专为ARM架构优化的JVM // 在M1 Mac上运行 java -version // openjdk version "17.x" // OpenJDK Runtime Environment (...) // OpenJDK 64-Bit Server VM (...) // on macOS-aarch64 // 性能优势: // - 原生ARM支持 // - 更好的性能 // - 更低的功耗 ``` --- ## Java 18 - 2022年 Java 18是一个小版本,专注于实用改进。 ### 核心特性 #### 1. UTF-8作为默认字符集 ```java // Java 18开始,UTF-8成为默认字符集 // 之前是平台相关的 // 文件读写默认使用UTF-8 Files.writeString(Paths.get("file.txt"), "你好,世界!"); // 读取文件 String content = Files.readString(Paths.get("file.txt")); // Properties文件默认UTF-8 Properties props = new Properties(); props.load(new FileReader("config.properties")); // String构造函数默认UTF-8 byte[] bytes = "你好".getBytes(StandardCharsets.UTF_8); // 显式指定 byte[] bytes2 = "你好".getBytes(); // 隐式UTF-8 // 之前的行为(平台相关) // Windows: GBK // Linux/Mac: UTF-8 // 现在: 统一UTF-8 ``` #### 2. 简单的Web服务器 ```java // Java 18提供了一个简单的Web服务器 // 用于测试和原型开发 // 命令行启动 jwebserver -p 8080 // Java代码启动 import jdk.httpserver.*; SimpleFileServer.createFileServer( new InetSocketAddress(8080), Paths.get("."), SimpleFileServer.OutputLevel.VERBOSE ).start(); // 特点: // - 仅用于开发测试 // - 静态文件服务 // - 不支持CGI或Servlet // - 不适用于生产环境 ``` #### 3. Java API文档改进 ```java // JavaDoc支持在代码中搜索 // 改进的HTML输出 /** * 一个示例类 * * @apiNote 这是一个API说明 * @implSpec 这是一个实现规范 * @implNote 这是一个实现说明 */ public class Example { /** * 示例方法 * * @param param1 第一个参数 * @return 返回值说明 * @throws IllegalArgumentException 参数非法时抛出 */ public String method(String param1) { return param1; } } ``` #### 4. reifyArrays工具 ```java // 数组操作工具类 import java.util.Arrays; // 将数组转换为List String[] array = {"A", "B", "C"}; List list = Arrays.asList(array); // 数组排序 Arrays.sort(array); // 数组二分查找 int index = Arrays.binarySearch(array, "B"); // 数组填充 Arrays.fill(array, "X"); // 数组复制 String[] copied = Arrays.copyOf(array, array.length); // 数组比较 boolean equal = Arrays.equals(array, copied); ``` #### 5. Vector API(第二轮孵化) ```java // 向量API第二轮孵化 import jdk.incubator.vector.*; // 更完善的向量操作 public static void vectorAdd(float[] a, float[] b, float[] result) { FloatVector species = FloatVector.SPECIES_PREFERRED; int i = 0; int upperBound = species.loopBound(a.length); for (; i < upperBound; i += species.length()) { FloatVector va = FloatVector.fromArray(species, a, i); FloatVector vb = FloatVector.fromArray(species, b, i); FloatVector vr = va.add(vb); vr.intoArray(result, i); } for (; i < a.length; i++) { result[i] = a[i] + b[i]; } } ``` #### 6. 互联网地址解析SPI ```java // SPI(Service Provider Interface)用于自定义地址解析 import java.net.spi.InetAddressResolver; import java.net.InetAddress; // 实现自定义解析器 public class CustomResolver implements InetAddressResolver { @Override public InetAddress[] lookupByName(String host) throws UnknownHostException { // 自定义解析逻辑 return new InetAddress[0]; } @Override public String lookupByAddress(byte[] addr) throws UnknownHostException { // 反向查找 return ""; } } ``` --- ## Java 19 - 2022年 Java 19引入了虚拟线程等重要预览特性。 ### 核心特性 #### 1. 虚拟线程(Virtual Threads - 预览) ```java // 虚拟线程 - 轻量级线程 import java.util.concurrent.*; // 创建虚拟线程 Thread.ofVirtual().start(() -> { System.out.println("Hello from virtual thread!"); }); // 使用ExecutorService ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); executor.submit(() -> { System.out.println("Task in virtual thread"); }); executor.shutdown(); // 大量虚拟线程 for (int i = 0; i < 1_000_000; i++) { Thread.ofVirtual().start(() -> { // 可以创建百万级别的虚拟线程 Thread.sleep(Duration.ofSeconds(1)); }); } // 虚拟线程vs平台线程对比 // 平台线程:重量级,受操作系统限制 // 虚拟线程:轻量级,由JVM调度 // 虚拟线程适合I/O密集型任务 // 同步代码与虚拟线程 public void processFiles() { try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { List> futures = files.stream() .map(file -> CompletableFuture.supplyAsync( () -> readFile(file), executor )) .toList(); List results = futures.stream() .map(CompletableFuture::join) .toList(); } } ``` #### 2. 结构化并发(Structured Concurrency - 预览) ```java // 结构化并发 - 管理并发任务的层次结构 import java.util.concurrent.*; import java.util.concurrent.StructuredTaskScope.*; public class StructuredConcurrencyDemo { public static void main(String[] args) { try { String result = process(); System.out.println(result); } catch (Exception e) { e.printStackTrace(); } } public static String process() throws Exception { try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { // 启动子任务 Subtask userTask = scope.fork(() -> fetchUser()); Subtask> ordersTask = scope.fork(() -> fetchOrders()); // 等待所有任务完成 scope.join().throwIfFailed(); // 合并结果 User user = userTask.get(); List orders = ordersTask.get(); return "User: " + user.name() + ", Orders: " + orders.size(); } } private static User fetchUser() { // 模拟用户查询 try { Thread.sleep(1000); return new User("John"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); } } private static List fetchOrders() { // 模拟订单查询 try { Thread.sleep(800); return List.of(new Order("Order1"), new Order("Order2")); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); } } } record User(String name) {} record Order(String id) {} ``` #### 3. switch的模式匹配(预览) ```java // switch的模式匹配 public static String formatter(Object obj) { return switch (obj) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); case Double d -> String.format("double %f", d); case String s -> String.format("String %s", s); default -> obj.toString(); }; } // 使用守卫 public static String test(Object obj) { return switch (obj) { case String s when s.length() > 5 -> "Long string: " + s; case String s -> "Short string: " + s; case Integer i when i > 0 -> "Positive integer: " + i; case Integer i -> "Non-positive integer: " + i; default -> "Other: " + obj; }; } // 与密封类结合 public static double area(Shape shape) { return switch (shape) { case Circle(double r) -> Math.PI * r * r; case Rectangle(double w, double h) -> w * h; case Triangle(double b, double height) -> 0.5 * b * height; }; } // 记录解构 public record Point(int x, int y) {} public record Rectangle(Point topLeft, Point bottomRight) {} public static String describe(Rectangle rect) { return switch (rect) { case Rectangle(Point(int x1, int y1), Point(int x2, int y2)) -> String.format("Rectangle: (%d,%d) to (%d,%d)", x1, y1, x2, y2); }; } ``` #### 4. 外部函数和内存API(第三轮预览) ```java // 外部函数和内存API import java.lang.foreign.*; import java.lang.invoke.*; // 分配堆外内存 try (MemorySegment segment = MemorySession.openImplicit()) { MemorySegment array = segment.allocate(10 * 4); // 10个int // 访问内存 VarHandle intHandle = MemoryLayout.sequenceLayout(10, MemoryLayout.valueLayout(32) ).varHandle(MemoryLayout.PathElement.sequenceElement()); intHandle.set(array, 0L, 42); int value = (int) intHandle.get(array, 0L); } // 调用C函数 try (MemorySession session = MemorySession.openImplicit()) { // 获取C函数句柄 Linker linker = Linker.nativeLinker(); SymbolLookup stdlib = linker.defaultLookup(); MethodHandle strlen = linker.downcallHandle( stdlib.find("strlen").get(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS) ); // 调用函数 MemorySegment str = session.allocateFrom("Hello"); long len = (long) strlen.invokeExact(str); System.out.println("Length: " + len); } ``` #### 5. Vector API(第四轮孵化) ```java // 向量API第四轮孵化 import jdk.incubator.vector.*; public static void vectorSqrt(double[] src, double[] dst) { FloatVector species = FloatVector.SPECIES_PREFERRED; int i = 0; int upperBound = species.loopBound(src.length); for (; i < upperBound; i += species.length()) { FloatVector v = FloatVector.fromArray(species, src, i); v = v.neg().mul(v.sqrt()); v.intoArray(dst, i); } for (; i < src.length; i++) { dst[i] = -src[i] * Math.sqrt(src[i]); } } ``` #### 6. Linux/RISC-V端口 ```java // Java 19支持RISC-V架构 // 适用于嵌入式系统和ARM设备 // 在RISC-V平台上运行 java -version // openjdk version "19" // OpenJDK Runtime Environment // OpenJDK 64-Bit Server VM (on linux-riscv64) ``` --- ## Java 20 - 2023年 Java 20继续完善预览特性。 ### 核心特性 #### 1. 虚拟线程(第二轮预览) ```java // 虚拟线程第二轮预览 // 与第一轮基本相同,但有细微改进 // 虚拟线程池 ExecutorService virtualExecutor = Executors.newVirtualThreadPerTaskExecutor(); // 批量提交任务 List> futures = new ArrayList<>(); for (int i = 0; i < 100; i++) { int taskId = i; futures.add(virtualExecutor.submit(() -> "Task " + taskId)); } // 获取结果 for (Future future : futures) { System.out.println(future.get()); } virtualExecutor.shutdown(); // 虚拟线程与同步API public void downloadFiles(List urls) { try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { List> downloads = urls.stream() .map(url -> CompletableFuture.supplyAsync( () -> downloadFile(url), executor )) .toList(); downloads.stream() .map(CompletableFuture::join) .forEach(System.out::println); } } ``` #### 2. 结构化并发(第二轮预览) ```java // 结构化并发第二轮预览 import java.util.concurrent.*; public static Response handleRequest(Request request) throws Exception { try (var scope = new StructuredTaskScope()) { // 并发执行多个子任务 Subtask authTask = scope.fork(() -> authenticate(request)); Subtask validateTask = scope.fork(() -> validate(request)); Subtask processTask = scope.fork(() -> process(request)); // 等待任务完成 scope.join(); // 处理结果 if (authTask.state() == Subtask.State.FAILED) { throw authTask.exception(); } if (validateTask.state() == Subtask.State.FAILED) { throw validateTask.exception(); } return processTask.get(); } } ``` #### 3. switch的模式匹配(第四轮预览) ```java // switch模式匹配第四轮预览 // 与之前版本基本相同 // 记录模式匹配 public sealed interface Shape permits Circle, Rectangle, Triangle {} public record Circle(double radius) implements Shape {} public record Rectangle(double width, double height) implements Shape {} public record Triangle(double base, double height) implements Shape {} public static String classify(Shape shape) { return switch (shape) { case Circle(double r) when r > 10 -> "Large circle"; case Circle(double r) -> "Small circle"; case Rectangle(double w, double h) when w == h -> "Square"; case Rectangle(double w, double h) when w > h -> "Wide rectangle"; case Rectangle(double w, double h) -> "Tall rectangle"; case Triangle t -> "Triangle"; }; } // 嵌套模式 public record Point(int x, int y) {} public record Box(Point topLeft, Point bottomRight) {} public static boolean isUnitBox(Box box) { return switch (box) { case Box(Point(0, 0), Point(1, 1)) -> true; default -> false; }; } ``` #### 4. 作用域值(Scoped Values - 预览) ```java // 作用域值 - 线程局部变量的替代品 import java.lang.ScopedValue; // 定义作用域值 static final ScopedValue USER = ScopedValue.newInstance(); static final ScopedValue REQUEST_ID = ScopedValue.newInstance(); public static void main(String[] args) { // 设置作用域值 ScopedValue.where(USER, "Alice") .where(REQUEST_ID, "req-123") .run(() -> { processRequest(); processWithVirtualThread(); }); } public static void processRequest() { // 读取作用域值 String user = USER.get(); String requestId = REQUEST_ID.get(); System.out.println("Processing for user: " + user); } public static void processWithVirtualThread() { // 作用域值自动传播到虚拟线程 Thread.ofVirtual().start(() -> { String user = USER.get(); // 可以访问 System.out.println("Virtual thread for user: " + user); }); } // 作用域值vs ThreadLocal // ThreadLocal: // - 需要手动清理 // - 容易内存泄漏 // - 不适用于虚拟线程 // // 作用域值: // - 自动清理 // - 不可变 // - 适用于虚拟线程 // - 自动传播到子线程 ``` #### 5. 外部函数和内存API(第二轮预览) ```java // 外部函数和内存API第二轮预览 // API更加简洁和类型安全 import java.lang.foreign.*; // 链接器 Linker linker = Linker.nativeLinker(); // 分配内存 try (MemorySession session = MemorySession.openImplicit()) { // 分配堆外内存 MemorySegment array = session.allocate(100); // 填充数据 for (int i = 0; i < 25; i++) { array.set(ValueLayout.JAVA_INT, i * 4L, i); } // 读取数据 for (int i = 0; i < 25; i++) { int value = array.get(ValueLayout.JAVA_INT, i * 4L); System.out.println("Array[" + i + "] = " + value); } } // 调用C标准库函数 public static long strlen(MemorySegment str) { Linker linker = Linker.nativeLinker(); SymbolLookup stdlib = linker.defaultLookup(); MethodHandle strlen = linker.downcallHandle( stdlib.find("strlen").get(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS) ); try { return (long) strlen.invokeExact(str); } catch (Throwable e) { throw new RuntimeException(e); } } ``` #### 6. Record Patterns(第二轮预览) ```java // 记录模式第二轮预览 public record Point(int x, int y) {} public record Rectangle(Point topLeft, Point bottomRight) {} // 解构记录 public static void printPoint(Point p) { if (p instanceof Point(int x, int y)) { System.out.println("Point at (" + x + ", " + y + ")"); } } // 嵌套解构 public static void printRectangle(Rectangle rect) { if (rect instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) { System.out.printf("Rectangle: (%d,%d) to (%d,%d)%n", x1, y1, x2, y2); } } // 在switch中使用 public static String describe(Object obj) { return switch (obj) { case Point(int x, int y) -> String.format("Point(%d, %d)", x, y); case Rectangle(Point(int x1, int y1), Point(int x2, int y2)) -> String.format("Rectangle[(%d,%d), (%d,%d)]", x1, y1, x2, y2); default -> "Unknown shape"; }; } ``` --- ## Java 21(LTS)- 2023年 ⭐ Java 21是最新LTS版本,引入了模式匹配、虚拟线程等重大特性。 ### 核心特性 #### 1. 虚拟线程(正式) ```java // 虚拟线程正式发布 // 轻量级线程,适合高并发场景 import java.util.concurrent.*; // 创建虚拟线程 Thread vt = Thread.ofVirtual().start(() -> { System.out.println("Virtual thread running"); }); // 虚拟线程池 ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); // 大量并发任务 List> futures = IntStream.range(0, 10000) .mapToObj(i -> CompletableFuture.supplyAsync( () -> processTask(i), executor )) .toList(); // 等待所有任务完成 List results = futures.stream() .map(CompletableFuture::join) .toList(); executor.shutdown(); // 虚拟线程vs传统线程对比 public class VirtualThreadDemo { public static void main(String[] args) throws Exception { // 传统线程 long start = System.currentTimeMillis(); try (ExecutorService service = Executors.newFixedThreadPool(100)) { for (int i = 0; i < 10000; i++) { service.submit(VirtualThreadDemo::simulateIO); } } System.out.println("Traditional: " + (System.currentTimeMillis() - start) + "ms"); // 虚拟线程 start = System.currentTimeMillis(); try (ExecutorService service = Executors.newVirtualThreadPerTaskExecutor()) { for (int i = 0; i < 10000; i++) { service.submit(VirtualThreadDemo::simulateIO); } } System.out.println("Virtual: " + (System.currentTimeMillis() - start) + "ms"); } private static void simulateIO() { try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } // 虚拟线程特点: // - 轻量级:内存占用少(KB级别) // - 可扩展:可创建百万级别的线程 // - 阻塞友好:阻塞不会浪费资源 // - 适合I/O密集型任务 // - 不适合CPU密集型任务 ``` #### 2. switch的模式匹配(正式) ```java // switch模式匹配正式发布 // 基本类型匹配 public static String getType(Object obj) { return switch (obj) { case null -> "null"; case Integer i -> "Integer: " + i; case Long l -> "Long: " + l; case Double d -> "Double: " + d; case String s -> "String: " + s; default -> "Other: " + obj.getClass().getSimpleName(); }; } // 记录解构 public record Point(int x, int y) {} public record Circle(Point center, double radius) {} public static String describeShape(Object shape) { return switch (shape) { case Point(int x, int y) -> String.format("Point at (%d, %d)", x, y); case Circle(Point(int cx, int cy), double r) -> String.format("Circle at (%d, %d), radius %.2f", cx, cy, r); default -> "Unknown shape"; }; } // 带守卫的模式 public static String classify(Object obj) { return switch (obj) { case String s when s.length() > 10 -> "Long string: " + s; case String s -> "Short string: " + s; case Integer i when i > 0 -> "Positive integer"; case Integer i -> "Non-positive integer"; default -> "Other type"; }; } // 密封类结合模式匹配 public sealed interface Shape permits Circle, Rectangle, Triangle {} public static double calculateArea(Shape shape) { return switch (shape) { case Circle(double r) -> Math.PI * r * r; case Rectangle(double w, double h) -> w * h; case Triangle(double b, double h) -> 0.5 * b * h; }; } ``` #### 3. 记录模式(正式) ```java // 记录模式正式发布 // 基本记录模式 public record Person(String name, int age) {} public static void greet(Person p) { if (p instanceof Person(String name, int age)) { System.out.printf("Hello %s, you are %d years old%n", name, age); } } // 嵌套记录模式 public record Address(String street, String city) {} public record User(String name, Address address) {} public static void printUserLocation(User user) { if (user instanceof User(String name, Address(String street, String city))) { System.out.printf("%s lives in %s, %s%n", name, city, street); } } // 在switch中使用记录模式 public static String describe(Object obj) { return switch (obj) { case Person(String name, int age) when age >= 18 -> String.format("Adult %s", name); case Person(String name, int age) -> String.format("Minor %s (%d)", name, age); case User(String name, Address(_, String city)) -> String.format("%s from %s", name, city); default -> "Unknown"; }; } // 复杂嵌套模式 public record Box(T content) {} public static String deepDescribe(Object obj) { return switch (obj) { case Box(Box(Person(String name, _))) -> "Box containing a box with " + name; case Box(Person(String name, int age)) -> String.format("Box with person %s, age %d", name, age); case Box(_) -> "Box with something else"; default -> "Not a box"; }; } ``` #### 4. 序列化集合(Sequenced Collections) ```java // 序列化集合 - 有序集合的统一接口 // List接口新增方法 List list = new ArrayList<>(List.of("A", "B", "C")); // 获取第一个和最后一个元素 String first = list.getFirst(); // "A" String last = list.getLast(); // "C" // 添加到首尾 list.addFirst("X"); // ["X", "A", "B", "C"] list.addLast("Y"); // ["X", "A", "B", "C", "Y"] // 移除首尾 list.removeFirst(); // ["A", "B", "C", "Y"] list.removeLast(); // ["A", "B", "C"] // 反转视图 List reversed = list.reversed(); // ["C", "B", "A"] // Set接口也支持 SequencedSet set = new LinkedHashSet<>(Set.of("A", "B", "C")); set.addFirst("X"); set.addLast("Y"); // Map接口支持 SequencedMap map = new LinkedHashMap<>(); map.putFirst("A", 1); map.putLast("Z", 26); map.firstEntry(); // Entry("A", 1) map.lastEntry(); // Entry("Z", 26) map.pollFirstEntry(); map.pollLastEntry(); // 所有有序集合的通用方法 // - getFirst() / getLast() // - addFirst() / addLast() // - removeFirst() / removeLast() // - reversed() ``` #### 5. 字符串模板(预览) ```java // 字符串模板预览特性 // 更简洁和安全的字符串格式化 // 基本模板 String name = "Alice"; int age = 30; String message = STR."Hello, \{name}! You are \{age} years old."; // "Hello, Alice! You are 30 years old." // 复杂表达式 String result = STR."The sum of 5 and 3 is \{5 + 3}."; // "The sum of 5 and 3 is 8." // 方法调用 String upper = STR."Name in uppercase: \{name.toUpperCase()}"; // "Name in uppercase: ALICE" // 多行模板 String html = STR."""

Hello, \{name}!

Age: \{age}

"""; // FMT模板 - 格式化 double price = 19.99; String formatted = FMT."Price: $%.2f\{price}"; // "Price: $19.99" // RAW模板 - 原始字符串 String raw = RAW."Path: C:\Users\{name}\Documents"; // "Path: C:\Users\Alice\Documents" // 与旧的字符串拼接对比 // 旧方式 String oldWay = "Hello, " + name + "! You are " + age + " years old."; // 新方式 String newWay = STR."Hello, \{name}! You are \{age} years old."; ``` #### 6. 未命名类和实例Main方法(预览) ```java // 未命名类 - 简化单文件程序 // 不需要public class和main方法的完整声明 // 旧方式 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } // 新方式 - 未命名类 void main() { System.out.println("Hello, World!"); } // 或者更简洁 System.out.println("Hello, World!"); // 带参数和返回值 String main(String[] args) { System.out.println("Args: " + Arrays.toString(args)); return "Done"; } // 实例方法 void main() { greet("World"); } void greet(String name) { System.out.println("Hello, " + name + "!"); } // 适合: // - 脚本编写 // - 快速原型 // - 学习和教学 // - 单文件应用 ``` #### 7. 作用域值(预览) ```java // 作用域值预览特性 // 线程局部变量的现代替代品 import java.lang.ScopedValue; // 定义作用域值 static final ScopedValue USER = ScopedValue.newInstance(); static final ScopedValue REQUEST_ID = ScopedValue.newInstance(); public static void main(String[] args) { // 设置作用域值并执行代码 ScopedValue.where(USER, "Alice") .where(REQUEST_ID, "req-123") .run(() -> { processRequest(); processWithVirtualThread(); }); } private static void processRequest() { // 访问作用域值 String user = USER.get(); System.out.println("Processing for: " + user); } private static void processWithVirtualThread() { // 作用域值自动传播到虚拟线程 Thread.ofVirtual().start(() -> { String user = USER.get(); // 可以访问父线程的作用域值 System.out.println("Virtual thread for: " + user); }); } // 与ThreadLocal对比 // ThreadLocal: // - 需要手动清理 // - 容易内存泄漏 // - 不适合虚拟线程 // // 作用域值: // - 自动清理 // - 不可变 // - 适合虚拟线程 // - 自动传播到子线程 ``` #### 8. 结构化并发(预览) ```java // 结构化并发预览特性 // 管理并发任务的层次结构 import java.util.concurrent.*; import java.util.concurrent.StructuredTaskScope.*; public static Response handleRequest(Request request) throws Exception { try (var scope = new ShutdownOnFailure()) { // 并发启动子任务 Subtask userTask = scope.fork(() -> fetchUser(request.userId())); Subtask> ordersTask = scope.fork(() -> fetchOrders(request.userId())); Subtask
addressTask = scope.fork(() -> fetchAddress(request.userId())); // 等待所有任务完成 scope.join().throwIfFailed(); // 合并结果 User user = userTask.get(); List orders = ordersTask.get(); Address address = addressTask.get(); return new Response(user, orders, address); } } // 带超时的结构化并发 public static Response handleRequestWithTimeout(Request request) throws Exception { try (var scope = new ShutdownOnFailure()) { // 设置超时 Future future = scope.fork(() -> { Subtask user = scope.fork(() -> fetchUser(request.userId())); Subtask> orders = scope.fork(() -> fetchOrders(request.userId())); scope.join(); return new Response(user.get(), orders.get()); }); // 等待结果或超时 return future.get(5, TimeUnit.SECONDS); } } // 结构化并发优势 // - 任务的层次结构清晰 // - 错误传播自动处理 // - 资源自动清理 // - 可取消性 // - 适用于虚拟线程 ``` #### 9. 分代ZGC(Generational ZGC) ```java // ZGC现在是分代的 // 更好的性能和更低的停顿时间 // 启动分代ZGC java -XX:+UseZGC MyApp // 分代ZGC特点 // - 年轻代和老年代分离 // - 更高的吞吐量 // - 更低的停顿时间 // - 更好的内存利用率 // 性能提升: // - 吞吐量提升20-30% // - 停顿时间减少 // - 大堆内存(TB级)表现更好 ``` #### 10. 密钥封装机制API ```java // 密钥封装机制API // 用于后量子密码学 import javax.crypto.*; // KEM封装和解封装 public class KEMDemo { public static void main(String[] args) throws Exception { // 创建KEM KeyPairGenerator kpg = KeyPairGenerator.getInstance("X25519"); KeyPair kp = kpg.generateKeyPair(); // 封装 KEM kem = KEM.getInstance("X25519"); KEM.Encapsulator enc = kem.newEncapsulator(kp.getPublic()); KEM.Encapsulated encapsulated = enc.encapsulate(16); // 解封装 KEM.Decapsulator dec = kem.newDecapsulator(kp.getPrivate()); SecretKey secretKey = dec.decapsulate(encapsulated.encapsulation()); System.out.println("Secret key: " + secretKey); } } ``` --- ## 版本对比与选择建议 ### LTS版本对比 | 特性 | Java 8 | Java 11 | Java 17 | Java 21 | |------|--------|---------|---------|---------| | 发布年份 | 2014 | 2018 | 2021 | 2023 | | Lambda/Stream | ✅ | ✅ | ✅ | ✅ | | 模块化 | ❌ | ✅ | ✅ | ✅ | | HTTP Client | ❌ | ✅ | ✅ | ✅ | | Records | ❌ | ❌ | ✅ | ✅ | | Pattern Matching | ❌ | ❌ | 部分 | ✅ | | Sealed Classes | ❌ | ❌ | ✅ | ✅ | | Virtual Threads | ❌ | ❌ | ❌ | ✅ | | Switch Expressions | ❌ | ❌ | ✅ | ✅ | | Text Blocks | ❌ | ❌ | ✅ | ✅ | ### 迁移路径建议 ``` Java 8 → Java 11(最小改动) Java 11 → Java 17(中等改动) Java 17 → Java 21(现代化升级) 直接从Java 8升级到Java 17/21: - 需要解决模块化问题 - 重新测试所有代码 - 更新依赖库 ``` ### 选择建议 **选择Java 8的情况**: - 遗留系统,无法升级 - 第三方库不支持新版本 - 团队熟悉Java 8生态 **选择Java 11的情况**: - 需要长期支持但不想大幅改动 - 大部分第三方库支持Java 11 - 需要更好的性能和安全性 **选择Java 17的情况**: - 新项目或可以接受中等改动的项目 - 需要Records、Pattern Matching等新特性 - 更好的代码可读性和安全性 **选择Java 21的情况**: - 新项目,追求最新特性 - 需要虚拟线程提升并发性能 - 需要模式匹配简化代码 - 长期维护的项目 --- ## 总结 Java的发展历程展示了其持续的演进和创新: ### 关键里程碑 1. **Java 5(2004)**:泛型、枚举、注解 - 现代Java的基石 2. **Java 8(2014)**:Lambda、Stream - 函数式编程革命 3. **Java 9(2017)**:模块化 - 生态系统重构 4. **Java 17(2021)**:Records、Sealed Classes - 现代化语言特性 5. **Java 21(2023)**:虚拟线程、模式匹配 - 并发和语法革新 ### 发展趋势 - **更简洁的语法**:模式匹配、记录类型、文本块 - **更好的性能**:虚拟线程、分代GC、向量API - **更强的安全性**:密封类、强封装、KEM API - **更好的并发模型**:结构化并发、作用域值 ### 最佳实践 1. **优先使用LTS版本**:Java 8, 11, 17, 21 2. **及时升级**:保持与技术栈同步 3. **拥抱新特性**:提升代码质量和开发效率 4. **测试充分**:升级前做好兼容性测试 --- > Java的未来:继续在性能、安全性和开发体验上创新。下一个LTS版本Java 25预计在2025年发布,值得期待! **推荐资源**: - [OpenJDK官网](https://openjdk.org/) - [Java 21发布说明](https://openjdk.org/projects/jdk/21/) - [Java特性路线图](https://openjdk.org/projects/jdk/) --- *本文涵盖Java 5到Java 21的所有重要特性,帮助你全面了解Java的演进历程。*
评论 0

发表评论 取消回复

Shift+Enter 换行  ·  Enter 发送
还没有评论,来发表第一条吧