赞
踩
Eclipse 基金会构建
名称:最初称为AdoptOpenJDK,现在作为Eclipse Foundation的一部分被重命名为Eclipse Adoptium。
是否免费:是,提供完全免费的JDK版本。
特点:提供HotSpot和OpenJ9两种JVM选项。Eclipse Adoptium项目承诺提供高质量的Java环境,并通过Eclipse Temurin提供Java开发工具包。
名称:Amazon Corretto
是否免费:是,提供完全免费的JDK版本,包括商业用途和生产环境。
特点:由亚马逊Web服务维护,提供长期支持(LTS),并且定期获取安全更新。
名称:Azul Zulu 是Java性能优化领域的先驱,提供Zulu作为完全兼容、高性能、可伸缩的Java平台。
是否免费:是,提供免费版本,同时Azul也提供付费的支持服务。
特点:适用于多种平台,包括Windows、macOS和Linux,以及云和容器环境。Azul Zulu提供长期支持版本和最新的Java版本。
名称:BellSoft Liberica JDK
是否免费:提供免费版本以及付费的商业支持。
特点:支持广泛的操作系统,包括Linux、Windows、macOS、及ARM设备。提供Alpine Linux上的小型Docker映像。
名称:Oracle OpenJDK
是否免费:是,Oracle在每个Java版本的首个六个月提供免费的OpenJDK版本,之后推荐转向Oracle JDK或其他提供长期支持的版本。
特点:Oracle提供的官方OpenJDK版本,通常作为最新Java版本的参考实现。Oracle OpenJDK提供最新的Java特性,它是开发和测试最新Java特性的前沿版本。这意味着它可能不像某些专为稳定性或长期支持设计的发行版那样适合生产环境。
名称:Red Hat Build of OpenJDK
是否免费:是,对于Red Hat Enterprise Linux(RHEL)客户,Red Hat提供的OpenJDK作为RHEL订阅的一部分而免费提供。此外,Red Hat也向OpenJDK社区贡献,并提供了一些版本供社区使用。
特点:适用于服务器、中间件和云环境,Red Hat为其OpenJDK版本提供长期支持。
开发环境:对于开发环境,任何上述提供的版本都是合适的。你可以根据个人偏好和额外特性(如Eclipse Temurin的Eclipse Adoptium项目或Amazon Corretto的长期支持)来选择。
生产环境:对于生产环境,考虑长期支持(LTS)和安全更新是关键。Amazon Corretto和Azul Zulu等都是很好的选择。
商业支持:如果需要商业支持,Azul Zulu、BellSoft Liberica JDK和Red Hat Build of OpenJDK提供付费支持服务。
背景:JDK 8是一个里程碑式的发布,它引入了Lambda表达式和流API,这两个特性极大地改变了Java程序的编写方式,使函数式编程成为可能。
主要特性:Lambda表达式、流API(Stream API)、新的日期时间API、接口的默认方法和静态方法。
代码示例
Arrays.asList(1,2,3,4,5,6,7,8,9).stream().forEach(a ->{
System.out.println("----"+ a);
});
interface Print { void print(); } interface MathOperation { int operation(int a, int b); } // 使用示例 public static void main(String[] args) { MathOperation operation = (a, b) -> a + b; System.out.println(operation.operation(4,5)); Print print = () -> System.out.print("---我是输出--"); print.print(); } // 输出 9 ---我是输出-- // 创建新的线程的使用示例 new Thread(() -> { for(int i=0; i < 5; i++) { System.out.println("Child Thread"); } }).start();
背景:JDK 9的开发重点是模块化系统(Project Jigsaw),这是Java平台最大的变革之一。它旨在帮助开发者构建和维护大型应用和库。
主要特性:模块系统(Java Platform Module System, JPMS)、JShell(交互式Java编程工具)、改进的Javadoc、私有接口方法。
先看示例:
代码结构
模块 greeting 提供方法 有2个类 只暴露一个类
module-info.java
module modular.greeting {
exports org.greeting.test;
}
package org.greeting.test;
public class Main {
public void print(){
System.out.println("6666666-greeting-main");
}
}
package org.greeting;
public class Main2 {
public void print(){
System.out.println("6666666-greeting-main2");
}
}
模块 consumer 使用方法
module-info.java
module modular.consumer {
requires modular.greeting;
}
package org.consumer;
import org.greeting.test.Main;
public class Test {
public static void main(String[] args) {
Main main = new Main();
main.print();
}
}
输出
6666666-greeting-main
Java 9模块化系统(Jigsaw项目)
目标:Java模块化系统的主要目标是提供一个更好的封装机制,通过明确的模块依赖来提高代码的可维护性和性能。它旨在解决JAR地狱问题,即复杂的类路径和库版本冲突问题。
作用范围:模块化系统是Java平台的一部分,它在Java语言级别和JVM级别提供支持。模块化不仅影响到代码的打包,还涉及到运行时的模块解析、模块隔离以及模块之间的接口暴露和访问控制。
功能:Java模块化提供了定义模块的功能,包括模块的名称、它所需的其他模块(依赖关系)、它向外提供的包等。这增强了代码的封装性,允许模块间明确的依赖关系定义,以及更精细的访问控制。
使用:在Java模块系统中,你需要创建module-info.java文件来声明模块的依赖、导出的包等信息。JVM在运行时会利用这些信息来确保所有必要的模块都可用,并按正确的方式相互作用。
Maven打Jar包
目标:Maven的主要目标是提供一个便捷的方式来构建项目,管理项目的生命周期、依赖、构建、测试、打包等。虽然Maven也支持依赖管理,但它更侧重于构建过程而非运行时的模块化。
作用范围:Maven主要用于项目构建时,不涉及到运行时的行为。它通过pom.xml文件管理项目的构建和依赖,但一旦项目被构建成Jar或War包,Maven的作用就结束了。
功能:使用Maven可以很容易地管理项目的依赖库、插件、生命周期等。它通过中央仓库自动下载依赖库,但不提供运行时的模块隔离或模块间接口的显式控制。
使用:在Maven项目中,你需要编辑pom.xml文件来添加依赖、配置插件等。Maven会根据这个文件自动处理依赖解析、编译、测试、打包等任务。
总结
Java 9模块化系统是一种运行时的模块管理机制,它改善了代码的封装性、可维护性,并提供了模块间明确的依赖关系和访问控制。
Maven主要关注于项目构建阶段,它通过自动化构建流程、管理依赖等功能来简化Java项目的构建和管理。
虽然两者在某种程度上都涉及到了代码组织和重用,但它们的关注点、目标和功能有着本质的不同。
启动JShell:
jshell
然后你可以直接输入Java代码并得到执行结果:
int a = 10;
int b = 20;
int sum = a + b;
System.out.println(sum);
在Java 9之前,接口只能有公共的抽象方法和默认方法。Java 9允许在接口中添加私有方法和私有静态方法,这有助于避免重复代码。
示例:
public interface MyInterface {
default void defaultMethod() {
privateMethod("Default Method");
}
private void privateMethod(String str) {
System.out.println(str);
}
}
添加了一些新的方法,比如takeWhile、dropWhile和ofNullable等,使得处理流数据更加灵活。
import java.util.stream.Stream; import java.util.List; import java.util.stream.Collectors; public class StreamApiExample { public static void main(String[] args) { // 使用ofNullable创建一个包含单个元素的流,如果元素为null,则创建一个空流 Stream<Integer> singleElementStream = Stream.ofNullable(5); singleElementStream.forEach(System.out::println); // 输出: 5 System.out.println("---"); // 使用ofNullable尝试创建一个空流 Stream<Integer> emptyStream = Stream.ofNullable(null); emptyStream.forEach(System.out::println); // 不输出任何内容 System.out.println("---"); // 创建一个数字流 Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 使用takeWhile获取流中所有小于5的元素 List<Integer> takenList = numberStream.takeWhile(n -> n < 5) .collect(Collectors.toList()); System.out.println("Taken While < 5: " + takenList); // 输出: [1, 2, 3, 4] // 这样是不是感觉和 filter 功能差不多? 不是这样的 // filter 是过滤所有元素 取合格的结果 // takeWhile 是从第一个元素开始,碰到一个不合格的元素后 直接结束 如果 上卖面的数字流是 1,5,4 那么输出结果是 1 // 重新创建数字流,因为流已经被消费 numberStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 使用dropWhile丢弃流中所有小于5的元素 List<Integer> droppedList = numberStream.dropWhile(n -> n < 5) .collect(Collectors.toList()); System.out.println("Dropped While < 5: " + droppedList); // 输出: [5, 6, 7, 8, 9, 10] } }
引入了一个新的HTTP客户端API,该API支持HTTP/2协议和WebSocket,并且比旧的HttpURLConnection更加易用和灵活。
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com"))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
背景:JDK 10是第一个在新的半年发布周期下发布的版本,这标志着Java平台的快速迭代和持续改进。
主要特性:局部变量类型推断(var关键字)、应用类数据共享、并行全垃圾回收、其他各种API和语言改进。
var list = new ArrayList<String>(); // 推断为ArrayList<String>
var stream = list.stream(); // 推断为Stream<String>
public class Main {
public static void main(String[] args) {
var user = new User();
System.out.println(user.userName);
}
}
class User{
public String userName = "wang";
}
Java 10增加了一种新的方式来创建不可变集合的副本。List.copyOf、Set.copyOf和Map.copyOf方法可以从现有的集合创建一个不可变副本。此外,Collectors类中也加入了toUnmodifiableList、toUnmodifiableSet和toUnmodifiableMap方法,以支持通过流操作收集结果为不可变集合。
var list = List.of("a", "b", "c");
var copyOfList = List.copyOf(list); // 创建一个不可变的副本
var unmodifiableList = list.stream()
.collect(Collectors.toUnmodifiableList()); // 通过流操作创建不可变列表
var value = Optional.of("Hello World");
// 如果Optional为空,则抛出NoSuchElementException
System.out.println(value.orElseThrow());
Java 10改进了JVM在容器环境中的运行,使其能够识别容器(如Docker)分配的资源限制(CPU、内存等),并据此优化运行时性能。
这个特性扩展了JVM的类数据共享(CDS)功能,允许应用程序类被放入共享的存档中。这样可以提高应用启动时间,并减少JVM的内存消耗。
背景:JDK 11是当前的长期支持(LTS)版本之一,它带来了几个重要的新特性和改进。
主要特性:HTTP Client API(标准化)、新的垃圾收集器ZGC和Epsilon、Lambda表达式的局部变量语法、删除Java EE和CORBA模块。
Java 11对String类引入了几个实用的新方法,这些方法使字符串处理更加方便。
isBlank(): 判断字符串是否为空或只包含空白字符。
lines(): 根据换行符将字符串分割成流(Stream)。
repeat(int): 将字符串重复给定次数。
strip(), stripLeading(), stripTrailing(): 去除字符串开头和/或结尾的空白字符,这是Unicode感知的,比trim()方法更加智能。
var str = " Java 11 \n \n is awesome! \n";
System.out.println(str.isBlank()); // false
str.lines().forEach(System.out::println); // 打印每行
System.out.println(str.repeat(2)); // 重复字符串
System.out.println(str.strip()); // 去除首尾空格
Java 11扩展了Java 10中引入的局部变量类型推断(使用var关键字),允许在Lambda表达式的参数中使用var。
var list = List.of("Java", "Python", "Go");
// 仔细想想 我们这个示例是不准确的,因为不用var 我们也能完成这一行 且更简单
list.forEach((var s) -> System.out.println(s.toUpperCase())); // 使用var声明Lambda表达式的参数
升级示例 假设我们有一个注解@NotNull,我们希望确保Lambda表达式中的参数不为null。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface NotNull {
}
现在,我们可以在Lambda表达式的参数中使用var,同时应用这个@NotNull注解:
import java.util.List;
public class LambdaWithVarExample {
public static void main(String[] args) {
List<String> languages = List.of("Java", "Kotlin", "Scala");
languages.forEach((@NotNull var language) -> System.out.println(language.toUpperCase()));
}
}
我们使用var来声明Lambda表达式的参数language,并且对它应用了@NotNull注解。虽然这个简单的例子中没有实际执行非空检查,但它展示了如何利用var在Lambda参数中添加注解的能力。这在某些特定场景下,比如使用依赖注入或进行静态代码分析时,是非常有用的。
添加了Files.readString和Files.writeString两个方法,简化了文件的读写操作。
Path path = Files.writeString(Files.createTempFile("test", ".txt"), "Java 11 features");
String content = Files.readString(path);
System.out.println(content); // 输出文件内容
Java 11正式引入了HTTP Client API(在Java 9中首次以Incubator模块引入),支持HTTP/1.1和HTTP/2,以及同步和异步的请求方式。
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://httpbin.org/get"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join(); // 异步发送请求并处理响应
如果你有一个名为HelloWorld.java的Java源文件,你可以直接使用以下命令运行它
java HelloWorld.java
这个命令会编译HelloWorld.java文件并运行它,无需手动编译。
背景:这些版本继续沿用半年一个版本的发布周期,集中在语言特性、性能、安全性以及JVM改进上。
主要特性:switch表达式的改进、记录类型(Record)、模式匹配的实例(instanceof的模式匹配)、封装内部API、Text Blocks(文本块)、Sealed Classes(密封类)。
增强的switch表达式,它支持使用箭头(->)来返回值,简化了传统的switch语句。
String day = "MONDAY";
String typeOfDay = switch (day) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
case "SATURDAY", "SUNDAY" -> "Weekend";
default -> "Invalid day";
};
System.out.println(typeOfDay); // 输出:Weekday
Java 13引入了文本块(Text Blocks),它允许字符串跨越多行,极大地简化了编写JSON、HTML等多行文本的方式。
这个功能很棒啊 有了文本块 再也不用想复杂的转义了 看起来也会舒服很多 python 有这东西 着实让人羡慕
String json = """
{
"name": "John",
"age": 30
}
""";
System.out.println(json);
Java 14将之前的预览特性switch表达式标准化,并引入了yield来返回值
String day = "SUNDAY";
String typeOfDay = switch (day) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
case "SATURDAY", "SUNDAY" -> "Weekend";
default -> {
yield "Invalid day";
}
};
System.out.println(typeOfDay); // 输出:Weekend
record Person(String name, int age) {}
Person person = new Person("John", 30);
System.out.println(person.name()); // 输出:John
密封类(Sealed Classes),它们用于限制哪些其他类可以继承该类。
sealed class Shape permits Circle, Square {
}
final class Circle extends Shape {
}
final class Square extends Shape {
}
正式将记录类型(Record)标准化。与JDK 14中相同,但现在是正式特性。
记录类型(Record)确实在某种程度上可以替代Lombok提供的部分功能,特别是关于自动生成getter和setter方法、toString、equals和hashCode方法的部分。记录(Record)是一种特殊形式的类,它是不可变的,编译器会自动生成所有的字段访问方法(字段本身是final的,所以只有getter方法),并且其主要目的是快速定义用来传输数据的简单对象(数据载体)。
record Person(String name, int age) {}
Person person = new Person("Alice", 25);
System.out.println(person.name()); // 输出:Alice
局限性:Record的目的是作为简单的数据载体,因此它们不能像常规类那样拥有额外的方法或状态(尽管可以定义静态方法和静态字段)。而Lombok则可以应用于任何类,提供更大的灵活性。
改进了instanceof操作符,允许直接在条件检查中声明变量,避免了显式转换。
Object obj = "Hello World!";
if (obj instanceof String s) {
System.out.println(s.toUpperCase()); // 输出:HELLO WORLD!
}
背景:JDK 17是下一个长期支持版本,包括多个重要的语言和JVM特性,标志着Java平台的进一步现代化。
主要特性:密封类的正式支持、模式匹配的增强(instanceof)、强化的伪随机数生成器、新的 macOS 渲染管道、移除实验性的 AOT 和 Graal JIT 编译器。
RandomGenerator random = RandomGenerator.getDefault();
int randomInt = random.nextInt(10, 50);
System.out.println(randomInt);
这里,RandomGenerator.getDefault()提供了一个默认的随机数生成器,nextInt(10, 50)生成一个介于10(含)到50(不含)之间的随机整数。
无示例
JEP 400使UTF-8成为Java API和JVM的默认字符集,这意味着无需特别指定字符集,就能更自然地处理跨平台文本数据。
在JDK 18之前
Files.readString(Path.of("example.txt"), StandardCharsets.UTF_8);
在JDK 18及以后
Files.readString(Path.of("example.txt"));
JEP 413提供了一种在Java API文档中嵌入代码片段的标准方式,通过@snippet标签,可以在Javadoc注释中包含可执行的代码示例。
/**
* Returns an example list.
*
* @return an example list
* @snippet :
* List<String> list = List.of("apple", "banana", "cherry");
* System.out.println(list);
*/
public List<String> exampleList() {
return List.of("apple", "banana", "cherry");
}
JEP 408引入了一个简单的HTTP服务器,用于开发和测试阶段,支持HTTP/1.1和WebSocket,无需额外的依赖或复杂配置。
jwebserver
这个命令会在当前目录启动一个HTTP服务器,监听8080端口。
待补充
虚拟线程示例来源 更加详细的讲解 请转至 此处
Thread.ofVirtual()和Thread.ofPlatform()是创建虚拟和平台线程的新API:
//输出线程ID 包括虚拟线程和系统线程 Thread.getId() 从jdk19废弃
Runnable runnable = () -> System.out.println(Thread.currentThread().threadId());
//创建虚拟线程
Thread thread = Thread.ofVirtual().name("testVT").unstarted(runnable);
testVT.start();
//创建虚平台线程
Thread testPT = Thread.ofPlatform().name("testPT").unstarted(runnable);
testPT.start();
使用Thread.startVirtualThread(Runnable)快速创建虚拟线程并启动
//输出线程ID 包括虚拟线程和系统线程
Runnable runnable = () -> System.out.println(Thread.currentThread().threadId());
Thread thread = Thread.startVirtualThread(runnable);
Thread.isVirtual()判断线程是否为虚拟线程:
//输出线程ID 包括虚拟线程和系统线程
Runnable runnable = () -> System.out.println(Thread.currentThread().isVirtual());
Thread thread = Thread.startVirtualThread(runnable);
Executors.newVirtualThreadPerTaskExecutor()创建一个 ExecutorService,该 ExecutorService 为每个任务创建一个新的虚拟线程:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("hello"));
}
JDK 11是当前的长期支持(LTS)版本之一,它带来了几个重要的新特性和改进。
static String formatterPatternSwitch(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();
};
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。