美文网首页
Java8学习笔记之其他语言特性

Java8学习笔记之其他语言特性

作者: 夏与清风 | 来源:发表于2019-08-14 16:23 被阅读0次

Java 8中包含三个语言特性的更新,分别是重复注解(repeated annotation)、类型注解(type annotation)和通用目标类型推断(generalized target-type inference)。

1、注解

Java 8在两个方面对注解机制进行了改进:

  • 可以定义重复注解
  • 可以为任何类型添加注解

Java中的注解是一种对程序元素进行配置,提供附加信息的机制(在Java 8之前,只有声明可以被注解)。它是某种形式的语法元数据(syntactic metadata)。比如,注解在JUnit框架中就使用得非常频繁。

@Before
public void setUp(){
  this.list = new ArrayList<>();
}
 
@Test
public void testAlgorithm(){
  ...
  assertEquals(5, list.size());
}

注解尤其适用于下面这些场景:

  • 在JUnit上下文中,使用注解能帮助区分哪些方法用于单元测试,哪些用于做环境搭建工作。
  • 注解可以用于文档编制。比如@Deprecated注解被广泛应用于说明某个方法不再推荐使用。
  • Java编译器还可以依据注解检查错误,禁止报警输出,甚至还能生成代码。
  • 注解在Java企业版中尤其流行,它们经常用于配置企业应用程序。
1)重复注解

之前版本的Java禁止对同样的注解类型声明多次。

@interface
Author {String name();}
 
@Author(name="Raoul") @Author(name="Mario") @Author(name="Alan") //错误:重复的注解
class Book{}  

程序员经常通过一些惯用法绕过这一限制。你可以声明一个新的注解,它包含了希望重复的注解数组。这种方法的形式如下:

@interface
Author {String name();}
@interface
Authors {Author[] value();}

@Authors(
  {@Author(name="Raoul"),@Author(name="Mario"),@Author(name="Alan")}
)
class Book{}

Book类的嵌套注解相当难看。这就是Java 8要从根本上移除这一限制的原因,去掉这一限制后,代码的可读性会好很多。现在,如果你的配置允许重复注解,你可以毫无顾虑地一次声明多个同一种类型的注解。它目前还不是默认行为,需要显式地要求进行重复注解。
如果一个注解在设计之初就是可重复的,你可以直接使用它。但是,如果提供的注解是为用户提供的,那么就需要做一些工作,说明该注解可以重复。下面是你需要执行的两个步骤:

  • 将注解标记为@Repeatable
  • 提供一个注解的容器
@Repeatable(Authors.class)
@interface
Author {
  String name();
}
@interface Authors {
  Author[] value();
}

@Author(name="Raoul") @Author(name="Mario") @Author(name="Alan")
class Book{}

编译时,Book会被认为使用了@Authors({@Author(name="Raoul"), @Author(name =”Mario”), @Author(name=”Alan”)})这样的形式进行了注解。可以把这种新的机制看成是一种语法糖,它提供了Java程序员之前利用的惯用法类似的功能。为了确保与反射方法在行为上的一致性,注解会被封装到一个容器中。
Java API中的getAnnotation(Class<T> annotation-Class)方法会为注解元素返回类型为T的注解。如果实际情况有多个类型为T的注解,该方法的返回到底是哪一个呢?
类Class提供了一个新的getAnnotationsByType方法,它可以帮助我们更好地使用重复注解。比如,可以像下面这样打印输出Book类的所有 Author注解:

public static void main(String[] args) {
  Author[] authors = Book.class.getAnnotationsByType(Author.class); //返回一个由重复注解Author组成的数组
  Arrays.asList(authors)
    .forEach(a -> {System.out.println(a.name());});
}
2)类型注解

从Java 8开始,注解已经能应用于任何类型。包括new操作符、类型转换、instanceof 检查、泛型类型参数,以及implements和throws子句。

@NonNull
String name = person.getName();

List<@NonNull Car> cars = new ArrayList<>();

Java 8并未提供官方的注解或者一种工具能以开箱即用的方式使用它们。它仅仅提供了一种功能,使用它可以对不同的类型添加注解。

2、通用目标类型推断

Java 8对泛型参数的推断进行了增强。比如,Java中的方法emptyList方法定义如下:

static <T> List<T> emptyList();

emptyList方法使用了类型参数T进行参数化。可以像下面这样为该类型参数提供一个显式的类型进行函数调用:

List<Car> cars = Collections.<Car>emptyList();

Java也可以推断泛型参数的类型。上面的代码和下面这段代码是等价的:

List<Car> cars = Collections.emptyList();

Java 8之前,这种推断机制依赖于程序的上下文(即目标类型),具有一定的局限性。比如下面这种情况就不大可能完成推断:

static void cleanCars(List<Car> cars) {}
cleanCars(Collections.emptyList());

会遭遇下面的错误:

cleanCars (java.util.List<Car>)cannot be applied to (java.util.List<java.lang.Object>)

为了修复此问题,只能提供一个显式的类型参数。Java 8中,目标类型包括向方法传递的参数,不再需要提供显式的泛型参数:

List<Car> cleanCars = dirtyCars.stream()
    .filter(Car::isClean)
    .collect(Collectors.toList());

Java 8的改进只需一句Collectors.toList()就能完成期望的工作,不再需要编写像Collectors.<Car>toList()这么复杂的代码了。

--参考文献《Java8实战》

相关文章

  • Java8学习笔记之其他语言特性

    Java 8中包含三个语言特性的更新,分别是重复注解(repeated annotation)、类型注解(type...

  • Java 8 新特性

    Java 8 新特性 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Java 8 (又称为...

  • Java8学习笔记-1

    Java8学习笔记-1序在java11即将面世的时候,终于开始行动学习java8的特性。目前没有机会实践,只是跟着...

  • 2018-10-28

    Java8学习笔记-1序在java11即将面世的时候,终于开始行动学习java8的特性。目前没有机会实践,只是跟着...

  • 方法引用

    方法引用(Method References) 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!...

  • Java8特性之Lambda、方法引用和Streams

    Java8特性之Lambda、方法引用和Streams Java8已经推出了好一段时间了,而掌握Java8的新特性...

  • Stream API

    Stream 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Stream API Java...

  • Lambda 表达式

    Lambda 表达式 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Lambda 表达式,...

  • 函数式接口

    函数式接口 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! 函数式接口(Functional...

  • Java8学习笔记目录

    Java8学习笔记 -- 接口的默认方法与静态方法 Java8学习笔记 -- Lambda表达式,Function...

网友评论

      本文标题:Java8学习笔记之其他语言特性

      本文链接:https://www.haomeiwen.com/subject/yapwjctx.html