Java 8 引入了许多新特性,这些特性极大地改善了开发者的编程体验和代码的简洁性。下面是一些Java 8开发中的进阶语法特性以及相应的案例代码:
Lambda 表达式:
Lambda 表达式允许你以匿名函数的形式来表示接口的实例,这对于编写简洁的代码非常有用,特别是当使用函数式接口时。
// 使用lambda表达式替代匿名类
List<String> names = Arrays.asList("John", "Jane", "Doe");
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
Stream API:
Stream API 是Java 8中引入的一组用于操作数据源(如集合)的高级迭代器。它提供了一种声明式的方式来处理数据。
// 使用Stream API来过滤、排序和打印列表中的元素
names.stream()
.filter(s -> s.startsWith("J"))
.sorted()
.forEach(System.out::println);
方法引用:
方法引用提供了一种引用方法而不执行它的方式。方法引用可以使你的代码更简洁、更清晰。
// 使用方法引用代替lambda表达式
names.forEach(System.out::println);
Optional 类:
Optional
类是一个容器对象,它可以包含也可以不包含非空值。这个类的引入是为了避免null
导致的问题。
// 使用Optional来避免NullPointerException
Optional<String> optionalName = names.stream().filter(s -> s.startsWith("J")).findFirst();
optionalName.ifPresent(name -> System.out.println("Found: " + name));
接口中的默认方法和静态方法:
Java 8 允许在接口中包含具有默认实现的方法和静态方法,这提供了更大的灵活性。
interface Vehicle {
default void print() {
System.out.println("I am a vehicle!");
}
static void blowHorn() {
System.out.println("Blowing horn!!!");
}
}
新的日期时间 API (java.time):
Java 8 引入了全新的日期时间API,它比老的Date
和Calendar
类更强大、更易于使用。
// 使用新的日期时间API
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.of(today, now);
System.out.println("Today's Date: " + today);
System.out.println("Current Time: " + now);
System.out.println("Current DateTime: " + dateTime);
CompletableFuture:
CompletableFuture
是异步编程的一种方式,它在Future
的基础上提供了更多的功能和灵活性。
// 使用CompletableFuture来异步执行任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Result of the asynchronous computation";
});
// 等待异步操作完成并获取结果
String result = future.get(); // 阻塞直到结果可用
System.out.println(result);
集合框架的增强:
Java 8为集合框架增加了新的方法,特别是对List
、Map
、Set
接口的增强。
// 使用Map的新方法getOrDefault
Map<String, Integer> nameMap = new HashMap<>();
Integer value = nameMap.getOrDefault("John", 0);
System.out.println(value); // 输出0,因为"John"并不在map中
// 使用Map的新方法putIfAbsent
nameMap.putIfAbsent("John", 1);
System.out.println(nameMap.get("John")); // 输出1
// 使用Map的新方法forEach
nameMap.forEach((key, val) -> System.out.println(key + " -> " + val));
并行Streams:
Java 8引入了并行流,它可以利用多核处理器的优势来加速数据处理。
// 并行处理集合元素
int sum = names.parallelStream()
.filter(s -> s.startsWith("J"))
.mapToInt(String::length)
.sum();
System.out.println("Total length of all names starting with 'J': " + sum);
Collectors:
Collectors
类提供了一系列用于处理Stream中数据的方法,可用于返回列表、字符串、甚至是数据分组。
// 使用Collectors来收集数据
List<String> filteredNames = names.stream()
.filter(s -> s.startsWith("J"))
.collect(Collectors.toList());
// 使用Collectors.joining()来连接字符串
String joined = names.stream()
.filter(s -> s.startsWith("J"))
.collect(Collectors.joining(", "));
System.out.println("Joined names: " + joined);
// 使用Collectors.groupingBy()进行分组
Map<Character, List<String>> groupedByName = names.stream()
.collect(Collectors.groupingBy(s -> s.charAt(0)));
System.out.println(groupedByName);
类型推断的增强:
Java 8引入了<>
操作符,也被称为"钻石操作符",可以与匿名内部类一起使用,在某些情况下增强了类型推断的能力。
// Java 7之前必须在构造器后重复泛型类型
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
// Java 8中可以省略构造器后的泛型类型
Map<String, List<String>> myMap8 = new HashMap<>();
Functional Interface:
Java 8在java.util.function
包中引入了一系列的函数式接口,比如Predicate
、Consumer
、Function
等。
// 使用Predicate函数式接口
Predicate<String> startsWithJ = (n) -> n.startsWith("J");
boolean isStartingWithJ = startsWithJ.test("John");
System.out.println("Does 'John' start with 'J'? " + isStartingWithJ);
// 使用Function函数式接口
Function<String, Integer> nameLength = String::length;
int length = nameLength.apply("John");
System.out.println("Length of 'John': " + length);
接口的默认方法:
Java 8允许在接口中定义默认方法,这些方法可以有自己的实现,而且不强制实现类覆盖它们。
interface MyInterface {
default void defaultMethod() {
System.out.println("This is a default method");
}
void abstractMethod();
}
class MyClass implements MyInterface {
public void abstractMethod() {
System.out.println("Abstract method implementation");
}
}
MyInterface obj = new MyClass();
obj.defaultMethod(); // 输出: This is a default method
obj.abstractMethod(); // 输出: Abstract method implementation
接口的静态方法:
Java 8允许在接口中定义静态方法,这些方法可以直接通过接口调用。
interface MyInterface {
static void staticMethod() {
System.out.println("This is a static method in an interface");
}
}
MyInterface.staticMethod(); // 输出: This is a static method in an interface
@FunctionalInterface 注解:
@FunctionalInterface
注解用于指示某个接口满足函数式接口的条件,即只有一个抽象方法的接口。
@FunctionalInterface
interface MyFunctionalInterface {
void execute();
}
MyFunctionalInterface fi = () -> System.out.println("Running execute()");
fi.execute(); // 输出: Running execute()
Java 8 新的数学函数:
Java 8在Math
类中加入了新的数学函数,比如floorDiv
、floorMod
等。
int result = Math.floorDiv(7, 3); // result -> 2
System.out.println(result);
新的Nashorn JavaScript引擎:
Java 8引入了新的Nashorn JavaScript引擎,允许在JVM上运行JavaScript代码。
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");
String code = "print('Hello Nashorn');";
nashorn.eval(code); // 输出: Hello Nashorn
新的网络功能:
Java 8增加了对HTTP/2协议的支持,并且引入了新的HTTP Client API。
// Java 11中引入的HttpClient,但Java 8中有HttpURLConnection等类可以使用
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Base64编码API:
Java 8引入了新的Base64编码和解码的API。
String originalInput = "test input";
String encodedString = Base64.getEncoder().encodeToString(originalInput.getBytes());
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String decodedString = new String(decodedBytes);
System.out.println(encodedString); // 输出编码后的字符串
System.out.println(decodedString); // 输出原始输入字符串
Type Annotations:
Java 8引入了对类型注解的支持,这允许你在任何使用类型的地方使用注解,例如在类型声明、类型转换、泛型和实现接口中。
// 使用类型注解来实现非空检查
public class NonNullExample {
public void myMethod(@NonNull String str) {
System.out.println(str);
}
}
重复注解:
在Java 8之前,一个位置上不能声明多个相同类型的注解。Java 8引入的@Repeatable
注解允许在同一个声明上使用多次同一个注解。
// 假设有一个可重复注解Hint
@Repeatable(Hints.class)
@interface Hint {
String value();
}
// 容器注解
@interface Hints {
Hint[] value();
}
// 使用重复注解
@Hint("hint1")
@Hint("hint2")
class Person {}
参数名称:
Java 8允许你通过反射访问方法和构造函数参数的名称,但需要在编译时使用-parameters
选项。
// 编译时要加上-parameters选项来保留参数名信息
public class ParameterNamesExample {
public void myMethod(String greeting, int count) {
// 方法体
}
}
// 反射获取参数名
Method method = ParameterNamesExample.class.getMethod("myMethod", String.class, int.class);
Parameter[] parameters = method.getParameters();
String parameterName1 = parameters[0].getName(); // greeting
String parameterName2 = parameters[1].getName(); // count
并发改进:
Java 8对并发编程进行了改进,特别是在ConcurrentHashMap
类和CompletableFuture
类中。
// ConcurrentHashMap的新方法
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("A", 1);
map.computeIfAbsent("B", key -> 2);
map.computeIfPresent("A", (key, val) -> val + 2);
// CompletableFuture的组合使用
CompletableFuture<String> future1
= CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2
= CompletableFuture.supplyAsync(() -> "World");
CompletableFuture<String> combinedFuture
= future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
String combined = combinedFuture.get(); // Hello World
IO/NIO 改进:
Java 8引入了对文件系统事件的监听器WatchService
,并且对文件I/O进行了一些改进,比如Files
类中的新方法。
// 使用Files类中的新方法
Path path = Paths.get("example.txt");
List<String> fileLines = Files.readAllLines(path, StandardCharsets.UTF_8);
Files.write(path, fileLines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
JDBC 4.2:
Java 8更新了JDBC API,包括对REF_CURSOR
类型的支持,以及改进了日期和时间的处理。
// JDBC中使用新的日期时间API
try (Connection connection = DriverManager.getConnection(url, username, password)) {
String sql = "SELECT * FROM events WHERE date > ?";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setObject(1, LocalDate.now());
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
// 处理结果集
}
}
}
}