Java 8 教程
“Java 仍然存在,人们开始理解它。”
欢迎阅读我对 Java 8 的介绍。本文将带您逐步了解从 Java 7 到 Java 8 的所有新功能。通过快速简单的代码示例,我们可以学习如何使用默认接口、
方法引用
和可重复的注释。在本文的最后,我们将熟悉 Stream API。
没有不必要的闲聊——只有代码和注释!向前!
接口的默认方法
Java 8 允许我们通过添加
default
. 此功能也称为
扩展方法。下面是第一个示例:
interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
除了抽象方法之外
calculate
,接口
Formula
还定义了默认方法
sqrt
。实现该接口的类只需实现
calculate
.
sqrt
可以直接使用 默认方法。
Formula formula = new Formula() {
@Override
public double calculate(int a) {
return sqrt(a * 100);
}
};
formula.calculate(100);
formula.sqrt(16);
该接口
Formula
作为匿名类实现。代码是多余的:6行用于实现
sqrt(a * 100)
。正如我们将在下一节中看到的,在 Java 8 中有一种更漂亮的方法来实现单个方法。
Lambda 表达式
让我们从一个在早期版本的 Java 中对字符串列表进行排序的简单示例开始:
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
静态方法
Collections.sort
接受一个列表和一个按列表排序顺序的比较器。您始终可以创建一个匿名比较器类并将其传递。在 Java 8 中,您可以编写更短的形式,即 lambda 表达式,而不是创建匿名类。
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
正如您所看到的,代码更短且更易于阅读。但这还可以变得更短:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
对于只有一行的正文,您可以跳过
{}
单词
return
。但你可以让它更短:
Collections.sort(names, (a, b) -> b.compareTo(a));
Java 编译器了解参数类型,因此您也可以跳过它们。让我们更深入地研究 lambda 表达式并了解如何使用它们。
功能接口
lambda 表达式如何适应 Java 类型系统?每个 lambda 对应于接口中描述的类型。因此,函数式接口应该只包含一个抽象方法。该类型的每个 lambda 表达式都将对应于该抽象方法。由于默认方法不是抽象的,因此您可以根据需要在功能接口中自由创建默认方法。如果该接口中只有一个抽象方法,我们还可以使用任意接口作为 lambda 表达式。为了满足这些要求,您需要添加
@FucntionalInterface
注释。编译器知道这一点,如果您想提供多个抽象方法,编译器会抛出异常。例子:
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);
请记住,如果
@FunctionalInterface
省略注释,代码也将编译。
方法和构造函数参考
上面的例子还可以通过使用方法引用变得更小:
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted);
Java 8 允许您通过添加
::
. 上面的示例显示了如何引用静态方法,尽管我们也可以引用非静态方法:
class Something {
String startsWith(String s) {
return String.valueOf(s.charAt(0));
}
}
Something something = new Something();
Converter<String, String> converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted);
让我们看看
::
它如何与构造函数一起工作。首先,我们将定义一个具有不同构造函数的示例类:
class Person {
String firstName;
String lastName;
Person() {}
Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
接下来,我们将定义一个用于创建新对象的接口:
interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);
}
我们不会实现创建工厂,而是将其与构造函数帮助结合在一起
::
:
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");
我们通过创建了到构造函数的链接
Person::new
。Java编译器将自动选择与方法签名匹配的正确构造函数
PersonFactory.create
。... 待续。不幸的是,我没有找到保存文章草稿的方法,这真的很奇怪,而且翻译的时间已经结束了——所以我稍后会完成它。适合所有了解并理解英文的人 -
原创文章。如果您有纠正翻译的建议,请以任何可用的方式写下来。
我的 Github 帐户
GO TO FULL VERSION