专注Java教育14年 全国咨询/投诉热线:444-1124-454
赢咖4LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java学习 Java1.8新特性介绍

Java1.8新特性介绍

更新时间:2022-09-08 11:42:21 来源:赢咖4 浏览793次

在本教程中,我们将快速浏览 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);

可选<T>

在 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新特性介绍”,如果大家想了解更多相关知识,不妨来关注一下赢咖4Java视频教程,里面的课程内容从入门到精通,细致全面,通俗易懂,适合没有基础的小伙伴学习,希望对大家能够有所帮助。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>