更新时间:2022-09-08 11:42:21 来源:极悦 浏览918次
在本教程中,我们将快速浏览 Java 8 中一些最有趣的新特性。
我们将讨论接口默认和静态方法、方法引用和可选。
在 Java 8 之前,接口只能有公共抽象方法。如果不强制所有实现类创建新方法的实现,就不可能向现有接口添加新功能,也不可能创建带有实现的接口方法。
从 Java 8 开始,接口可以具有静态和默认方法,尽管在接口中声明了这些方法,但它们具有已定义的行为。
1.静态方法
考虑接口的这个方法(我们称这个接口Vehicle):
static String producer() {
return "N&F Vehicles";
}
静态producer()方法只能通过接口和在接口内部使用。它不能被实现类覆盖。
要在接口外调用它,应使用静态方法调用的标准方法:
String producer = Vehicle.producer();
2.默认方法
默认方法是使用新的default关键字声明的。这些可以通过实现类的实例访问,并且可以被覆盖。
让我们为Vehicle接口添加一个默认方法,该方法也会调用该接口的静态方法:
default String getOverview() {
return "ATV made by " + producer();
}
假设这个接口是由类VehicleImpl实现的。
为了执行默认方法,应该创建这个类的一个实例:
Vehicle vehicle = new VehicleImpl();
String overview = vehicle.getOverview();
方法引用可用作仅调用现有方法的 lambda 表达式的更短且更易读的替代方案。方法引用有四种变体。
1.引用静态方法
对静态方法的引用包含语法ContainingClass::methodName。
我们将尝试在Stream API 的帮助下计算List<String>中的所有空字符串:
boolean isReal = list.stream().anyMatch(u -> User.isRealUser(u));
让我们仔细看看anyMatch()方法中的 lambda 表达式。它只是调用User类的静态方法isRealUser(User user)
因此,它可以用对静态方法的引用代替:
boolean isReal = list.stream().anyMatch(User::isRealUser);
这种类型的代码看起来信息量更大。
2.引用实例方法
对实例方法的引用包含语法containsInstance::methodName。
以下代码调用User类型的isLegalName(String string)方法,该方法验证输入参数:
User user = new User();
boolean isLegalName = list.stream().anyMatch(user::isLegalName);
3.引用特定类型对象的实例方法
此引用方法采用语法ContainingType::methodName。
让我们看一个例子:
long count = list.stream().filter(String::isEmpty).count();
4.对构造函数的引用
对构造函数的引用采用语法ClassName::new。
由于 Java 中的构造函数是一种特殊的方法,因此方法引用也可以应用到它,借助new 作为方法名称:
Stream<User> stream = list.stream().map(User::new);
在 Java 8 之前,开发人员必须仔细验证他们引用的值,因为可能会抛出NullPointerException (NPE)。所有这些检查都需要非常烦人且容易出错的样板代码。
Java 8 Optional<T>类可以帮助处理有可能获得NPE的情况。它用作T类型对象的容器。如果此值不是null ,它可以返回此对象的值。当此容器内的值为null时,它允许执行一些预定义的操作,而不是抛出NPE。
1.创建可选<T>
Java8Optional类的实例可以在其静态方法的帮助下创建。
让我们看看如何返回一个空的Optional:
Optional<String> optional = Optional.empty();
接下来,我们返回一个包含非空值的Optional :
String str = "value";
Optional<String> optional = Optional.of(str);
最后,如果参数为null ,则返回具有特定值的Optional或空Optional的方法如下:
Optional<String> optional = Optional.ofNullable(getString());
2.可选<T>用法
假设我们希望得到一个List<String>,在null的情况下,我们想用一个新的ArrayList<String>实例来替换它。
对于 Java 8 之前的代码,我们需要执行以下操作:
List<String> list = getList();
List<String> listOpt = list != null ? list : new ArrayList<>();
使用 Java 8,可以使用更短的代码实现相同的功能:
List<String> listOpt = getList().orElseGet(() -> new ArrayList<>());
当我们需要以旧方式访问某个对象的字段时,甚至还有更多样板代码。
假设我们有一个User类型的对象,它有一个Address类型的字段和一个String类型的字段 s treet ,如果存在,我们需要返回street字段的值,如果street为null ,我们需要返回默认值:
User user = getUser();
if (user != null) {
Address address = user.getAddress();
if (address != null) {
String street = address.getStreet();
if (street != null) {
return street;
}
}
}
return "not specified";
这可以用Optional来简化:
Optional<User> user = Optional.ofNullable(getUser());
String result = user
.map(User::getAddress)
.map(Address::getStreet)
.orElse("not specified");
在此示例中,我们使用map()方法将调用getAdress()的结果转换为Optional<Address>和getStreet()转换为Optional<String>。如果这些方法中的任何一个返回null,则map()方法将返回一个空Optional。
现在想象我们的 getter 返回Optional<T>。
在这种情况下,我们应该使用flatMap()方法而不是map():
Optional<OptionalUser> optionalUser = Optional.ofNullable(getOptionalUser());
String result = optionalUser
.flatMap(OptionalUser::getAddress)
.flatMap(OptionalAddress::getStreet)
.orElse("not specified");
Optional的另一个用例是更改NPE,但有另一个例外。
所以,就像我们之前所做的那样,让我们尝试以 Java 8 之前的风格来做这件事:
String value = null;
String result = "";
try {
result = value.toUpperCase();
} catch (NullPointerException exception) {
throw new CustomException();
}
如果我们使用Optional <String>,答案会更易读、更简单:
String value = null;
Optional<String> valueOpt = Optional.ofNullable(value);
String result = valueOpt.orElseThrow(CustomException::new).toUpperCase();
以上就是关于“Java1.8新特性介绍”,如果大家想了解更多相关知识,不妨来关注一下极悦Java视频教程,里面的课程内容从入门到精通,细致全面,通俗易懂,适合没有基础的小伙伴学习,希望对大家能够有所帮助。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习