Java是一种广泛使用的编程语言,拥有一个庞大的社区和大量的生态系统。自从Java的早期版本以来,它已经经历了许多变化和改进。在这篇文章中,我们将详细介绍Java各个版本的新特性,并使用代码示例进行说明。
Java 1.0是Java的第一个版本,它引入了面向对象编程(OOP)的基本概念。这个版本的新特性包括:
以下是一个简单的Java 1.0程序示例:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Java 1.2引入了Java Class Library,将Java的核心类库整合到了一起。这个版本的新特性包括:
以下是一个使用Java 1.2的示例程序,用于创建一个简单的GUI窗口:
import javax.swing.*;
public class MyWindow {
public static void main(String[] args) {
JFrame frame = new JFrame("My Window");
JButton button = new JButton("Click Me");
frame.add(button);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Java 5.0引入了许多新的语言特性,以提高开发效率。这个版本的新特性包括:
以下是一个使用Java 5.0的示例程序,用于创建一个泛型集合:
import java.util.*;
public class MyCollection<T> {
private List<T> elements;
public MyCollection() {
elements = new ArrayList<T>();
}
public void add(T element) {
elements.add(element);
}
public T get(int index) {
return elements.get(index);
}
}
Java 6引入了新的并发集合类,如ConcurrentHashMap、CopyOnWriteArrayList等,以提供更好的并发性能。此外,还增强了Map接口,添加了几个新的方法,如putIfAbsent、remove等。下面是一个使用ConcurrentHashMap的例子:
import java.util.concurrent.*;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println(map.get("one"));
});
}
executor.shutdown();
}
}
Java 6引入了ScriptEngineManager类,用于执行脚本引擎。通过使用脚本引擎,可以将Java应用程序与JavaScript、Groovy等脚本语言集成。下面是一个使用JavaScript引擎的例子:
import javax.script.*;
public class ScriptEngineExample {
public static void main(String[] args) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.eval("var a = 1 + 2; print('The value of a is ' + a);");
}
}
Java 6提供了更强大的XML处理功能,包括XPath表达式、XMLStreamReader和XMLStreamWriter等。下面是一个使用XPath表达式的例子:
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import javax.xml.xpath.*;
public class XPathExample {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("example.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/root/element[@attribute='value']";
NodeList nodeList = (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
System.out.println(node.getTextContent());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
在Java 7中,switch语句可以用于字符串类型,并且支持字符串的相等比较。下面是一个使用字符串类型switch语句的例子:
public class StringSwitchExample {
public static void main(String[] args) {
String str = "apple";
switch (str) {
case "apple":
System.out.println("It's an apple");
break;
case "banana":
System.out.println("It's a banana");
break;
default:
System.out.println("It's something else");
}
}
}
Java 7引入了try-with-resources语句,可以自动关闭实现了AutoCloseable接口的资源。下面是一个使用try-with-resources语句的例子:
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在上面的例子中,BufferedReader将自动关闭,无论try块中是否发生异常。
Java 7引入了泛型类型推断,可以减少泛型代码的复杂性。下面是一个使用泛型类型推断的例子:
public class GenericTypeInferenceExample<T> {
private T element;
public GenericTypeInferenceExample(T element) {
this.element = element;
}
public T getElement() {
return element;
}
public static void main(String[] args) {
GenericTypeInferenceExample<String> example = new GenericTypeInferenceExample<>("hello");
System.out.println(example.getElement());
}
}
在上面的例子中,类型参数T被推断为字符串类型,无需显式指定。
Java 8引入了Lambda表达式,可以简化匿名内部类的编写。下面是一个使用Lambda表达式的例子:
public class LambdaExample {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.forEach(System.out::println);
}
}
在上面的例子中,Lambda表达式System.out::println表示一个方法引用,它指向了System.out对象的println方法。Lambda表达式可以用于替代匿名内部类的编写。
Java 8引入了流API,可以方便地处理数据集合。下面是一个使用流API的例子:
public class StreamExample {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream().forEach(System.out::println);
}
}
在上面的例子中,stream()方法将List转换成了一个流,然后可以使用forEach方法来遍历流中的元素。使用流API可以更加高效地处理数据集合。
Java 8引入了函数式接口,使得Lambda表达式和流API的使用更加方便。函数式接口是一个只有一个抽象方法的接口,可以被Lambda表达式所实现。下面是一个使用函数式接口的例子:
@FunctionalInterface
interface Action {
void execute();
}
public class Main {
public static void main(String[] args) {
Action action = () -> System.out.println("Hello World!");
action.execute();
}
}
在上面的例子中,定义了一个函数式接口Action,它只有一个抽象方法execute()。然后使用Lambda表达式实现了这个接口,并调用了execute()方法。
Java 8引入了Optional类型,它可以避免NullPointerException,使得代码更加健壮和安全。下面是一个使用Optional类型的例子:
public class Main {
public static void main(String[] args) {
Optional<String> optional = Optional.of("Hello World!");
optional.ifPresent(str -> System.out.println(str));
}
}
在上面的例子中,使用Optional.of方法创建了一个Optional对象,然后使用ifPresent方法判断Optional对象是否为空,如果不为空则输出该对象的内容。使用Optional类型可以避免在访问空对象时抛出NullPointerException。
以上就是Java 8及其后续版本中的一些新特性,这些特性都极大地提高了Java语言的开发效率和代码简洁性。
Java 9引入了模块化系统,允许将代码划分为独立的模块。这样可以更好地组织和管理代码,并提高了代码的复用性和可维护性。下面是一个使用Java 9模块化系统的例子:
module com.example.myapp {
requires java.desktop;
exports com.example.myapp;
}
在上面的例子中,我们定义了一个名为com.example.myapp的模块,需要使用java.desktop模块,并导出com.example.myapp包。
Java 9对集合API进行了改进,引入了一些新的接口和实现类,如List.of()、Set.of()、Map.of()等。这些新的API提供了更加方便和灵活的方式来创建不可变的集合。下面是一个使用List.of()的例子:
List<String> myList = List.of("apple", "banana", "cherry");
在上面的例子中,我们使用List.of()方法创建了一个包含三个字符串元素的不可变列表。
Java 9引入了HTTP 2.0协议的实现,提供了更加高效和灵活的HTTP通信功能。下面是一个使用HTTP 2.0的例子:
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class HttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://www.example.com"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
在上面的例子中,我们使用HttpClient类发送了一个HTTP GET请求,并获取了响应的文本内容。使用Java 9的HTTP 2.0 API可以提供更高的性能和更好的流控制。
Java 10引入了局部变量类型推断,可以在方法中的变量声明时省略类型。这使得代码更加简洁,提高了开发效率。下面是一个使用局部变量类型推断的例子:
public class LocalVariableTypeInferenceExample {
public static void main(String[] args) {
var names = new String[]{"Alice", "Bob", "Charlie"};
for (var name : names) {
System.out.println(name);
}
}
}
在上面的例子中,我们使用了var关键字来声明变量names,并使用了数组初始化器来初始化它。局部变量类型推断使得代码更加简洁和易于阅读。
Java 10对Switch表达式进行了改进,允许使用字符串作为case标签。这使得在处理字符串类型的数据时更加方便。下面是一个使用改进的Switch表达式的例子:
public class SwitchExpressionExample {
public static void main(String[] args) {
String fruit = "apple";
switch (fruit) {
case "apple":
System.out.println("It's an apple");
break;
case "banana":
System.out.println("It's a banana");
break;
case "cherry":
System.out.println("It's a cherry");
break;
default:
System.out.println("It's something else");
}
}
}
在上面的例子中,我们使用了字符串作为case标签来匹配不同的水果类型。这使得代码更加灵活和易于阅读。
Java 10对集合API进行了改进,引入了一些新的接口和实现类,如List.of()、Set.of()、Map.of()等。这些新的API提供了更加方便和灵活的方式来创建不可变的集合。下面是一个使用改进的集合API的例子:
import java.util.List;
import java.util.Set;
import java.util.Map;
public class CollectionAPIExample {
public static void main(String[] args) {
List<String> myList = List.of("apple", "banana", "cherry");
Set<String> mySet = Set.of("apple", "banana", "cherry");
Map<String, Integer> myMap = Map.of("apple", 1, "banana", 2, "cherry", 3);
System.out.println(myList);
System.out.println(mySet);
System.out.println(myMap);
}
}
在上面的例子中,我们使用List.of()、Set.of()、Map.of()方法创建了不可变的列表、集合和映射。这些新的API提供了更加方便和灵活的方式来创建不可变的集合,避免了手动创建和修改集合的麻烦。
ZGC和Shenandoah是两种新的垃圾收集器,它们的主要目标是解决在大型内存消耗和高吞吐量场景下,传统垃圾收集器带来的显著停顿问题。
以下是使用ZGC的示例代码:
import java.util.ArrayList;
import java.util.List;
public class ZGCTest {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
while (true) {
byte[] bytes = new byte[1024 * 1024]; // 1MB
list.add(bytes); // 不断添加新对象,模拟高吞吐量场景
}
}
}
在运行上述代码时,可以通过-XX:+UseZGC参数指定使用ZGC。
Java 11引入了一种新的Switch表达式语法,允许在case子句中直接返回结果,使代码更简洁、易读。
以下是使用Switch表达式的示例代码:
public class SwitchExpressionExample {
public static void main(String[] args) {
var fruit = "apple";
var price = switch (fruit) {
case "apple" -> 2.99;
case "banana" -> 1.99;
case "cherry" -> 0.99;
default -> 0.0;
};
System.out.println("The price of " + fruit + " is " + price);
}
}
Java 11对List API进行了改进,新增了List.of()和List.ofCopy()方法,用于创建不可变的列表。此外,还新增了List.copyOf()方法,用于创建一个由给定集合转换而来的可变列表。
以下是使用改进的List API的示例代码:
import java.util.*;
public class ListAPIExample {
public static void main(String[] args) {
List<String> myList = List.of("apple", "banana", "cherry"); // 使用List.of()创建不可变列表
List<String> myCopiedList = List.ofCopy(myList); // 使用List.ofCopy()创建包含副本的不可变列表
List<String> myCopy = List.copyOf(myList); // 使用List.copyOf()创建由给定集合转换而来的可变列表
System.out.println(myList); // 输出:[apple, banana, cherry] (原始列表不会被修改)
}
}
Java 12引入了局部变量类型推断,使得我们可以省略局部变量的类型声明。这使得代码更加简洁,同时也提高了IDE的功能。
以下是使用局部变量类型推断的示例代码:
public class LocalVariableInferenceExample {
public static void main(String[] args) {
var numbers = List.of(1, 2, 3, 4, 5);
for (var number : numbers) {
System.out.println(number);
}
}
}
在上述代码中,我们使用var关键字来声明numbers和number变量,Java编译器能够根据上下文自动推断出这些变量的类型。
Java 12引入了一种新的Switch表达式,使得编写switch语句更加简洁。新的Switch表达式允许在case子句中直接返回结果,无需使用break语句。
以下是使用新的Switch表达式的示例代码:
public class SwitchExpressionExample {
public static void main(String[] args) {
var value = "apple";
var fruit = switch (value) {
case "apple" -> "Red Apple";
case "banana" -> "Yellow Banana";
case "cherry" -> "Red Cherry";
default -> "Unknown Fruit";
};
System.out.println(fruit);
}
}
在上述代码中,我们使用switch语句和->操作符来直接返回结果,这使得代码更加简洁和易读。
Java 13对Switch表达式进行了进一步的改进,引入了新的语法来处理没有break的case子句。现在,我们可以使用yield关键字来直接返回结果。
以下是使用改进的Switch表达式的示例代码:
public class ImprovedSwitchExpressionExample {
public static void main(String[] args) {
var value = "apple";
var fruit = switch (value) {
case "apple" -> yield "Red Apple";
case "banana" -> yield "Yellow Banana";
case "cherry" -> yield "Red Cherry";
default -> yield "Unknown Fruit";
};
System.out.println(fruit);
}
}
在上述代码中,我们使用yield关键字来直接返回结果,这使得代码更加简洁和易读。同时,yield关键字也使得代码更加清晰,因为它明确表示了这是一个返回值。
Java 13引入了文本块功能,这使得我们可以更方便地处理多行字符串。文本块可以自动进行字符串转义和合并,无需我们手动处理。
以下是使用文本块的示例代码:
public class TextBlockExample {
public static void main(String[] args) {
var text = """
This is a text block.
It can contain multiple lines of text.
We don't need to manually handle string concatenation or escaping. """;
System.out.println(text);
}
}
在上述代码中,我们使用三个双引号(“”")来创建一个文本块,并直接在其中写入多行文本。Java编译器会自动处理字符串的转义和合并。
Java 14引入了Records特性,这是一个简化Java类的创建和使用的功能。Records允许我们以更简洁的方式创建数据类,同时提供了一些内置的保证,如线程安全和清晰的初始化。
以下是使用Records的示例代码:
public record Person(String name, int age) {}
public class Main {
public static void main(String[] args) {
Person person = Person.of("John Doe", 30);
System.out.println(person.name());
System.out.println(person.age());
}
}
在上述代码中,我们使用record关键字来定义Person记录,并使用构造函数来初始化它的字段。Person.of方法用于创建Person对象,并自动生成了name()和age()方法的访问器。
Java 14引入了Text Blocks特性,这使得我们可以更方便地处理多行文本。Text Blocks提供了一种新的语法来创建和操作字符串,使得代码更加简洁和易读。
以下是使用Text Blocks的示例代码:
public class TextBlockExample {
public static void main(String[] args) {
String text = """
This is a text block.
It can contain multiple lines of text.
We don't need to manually handle string concatenation or escaping. """;
System.out.println(text);
}
}
在上述代码中,我们使用三个双引号(“”")来创建一个Text Block,并直接在其中写入多行文本。Java编译器会自动处理字符串的转义和合并。
Java 14对Switch语句进行了进一步的改进,引入了Pattern Matching功能。这个功能使得我们可以根据不同的模式对case子句进行匹配,提高了Switch语句的灵活性和可读性。
以下是使用Pattern Matching的示例代码:
java
public class PatternMatchingExample {
public static void main(String[] args) {
var value = “apple”;
var fruit = switch (value) {
case “apple”, “banana”, “cherry” -> "Fruit: " + value;
default -> “Unknown”;
};
System.out.println(fruit);
}
}
在上述代码中,我们使用switch语句和->操作符来根据不同的模式对case子句进行匹配。如果满足条件,则直接返回结果;否则,执行下一个case子句,直到找到匹配的case或者到达默认case。这个特性使得代码更加简洁、易于阅读和理解。
Java 21后续版本的新特性有:
虚拟线程:是轻量级线程,承诺“显著”减少编写、维护和观察高吞吐量并发应用程序的工作量。该计划的目标包括使以简单线程请求方式编写的服务器应用程序能够以接近最佳的硬件利用率进行扩展,使使用lang.thread API的现有代码能够采用变化最小的虚拟线程,并使用当前JDK工具轻松调试和分析虚拟线程。
序列集合:引入了接口来表示具有定义的相遇顺序的集合。每个集合都有定义明确的第一和第二元素,依此类推,直到最后一个元素。提供了统一的API来接受第一个和最后一个元素,并以相反的顺序处理元素。