Java 8 基础API的一些小的该进

Java8是一个较大改变的版本,包含了API和库方面的修正,它还对我们常用的API进行很多微小的调整, 下面我会带你了解字符串、集合、注解等新方法。

字符串

经常会遇到这样一种情况, 需要将一组字符串按特定格式拼接起来。

之前的写法

String message = "Java"+"-"+"is"+"-"+"cool";

Java 8的join写法

String message = String.join("-", "Java", "is", "cool");

当然更多的时候是要遍历集合里的字符串,然后按特定格式拼接:

之前的写法

List<String> strings = new LinkedList<>();
strings.add("Java");
strings.add("is");
strings.add("cool");
        
String message = "";
for (int i = 0; i < strings.size(); i++) {
    message += strings.get(i)+"-";
}
message = message.substring(0, message.length()-1);

join写法

List<String> strings = new LinkedList<>();
strings.add("Java");strings.add("is");
strings.add("cool");
String message = String.join(" ", strings);

第一个参数是分隔符,后面接收一个CharSequence类型的可变参数数组或一个Iterable。

集合

集合改变中最大的当属前面章节中提到的Stream API,除此之外还有一些小的改动。

  • Map中的很多方法对并发访问十分重要,我们将在后面的章节中介绍
  • Iterator提供forEachRemaining将剩余的元素传递给一个函数
  • BitSet可以产生一个Stream对象

通用目标类型判断

Java8对泛型参数的推断进行了增强。相信你对Java8之前版本中的类型推断已经比较熟悉了。 比如,Collections中的方法emptyList方法定义如下:

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

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

List<Person> persons = Collections.<Person>emptyList();

不过编译器也可以推断泛型参数的类型,上面的代码和下面这段代码是等价的:

List<Person> persons = Collections.emptyList();

我还是习惯于这样书写。

注解

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

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

重复注解

之前版本的Java禁止对同样的注解类型声明多次。由于这个原因,下面的第二句代码是无效的:

@interface Basic {
    String name();
}
@Basic(name="fix")
@Basic(name="todo")
class Person{ }

我们之前可能会通过数组的做法绕过这一限制:

@interface Basic {
    String name();
}
@interface Basics {
    Basic[] value();
}
@Basics( { @Basic(name="fix") , @Basic(name="todo") } )
class Person{ }

Book类的嵌套注解相当难看。这就是Java8想要从根本上移除这一限制的原因,去掉这一限制后, 代码的可读性会好很多。现在,如果你的配置允许重复注解,你可以毫无顾虑地一次声明多个同一种类型的注解。 它目前还不是默认行为,你需要显式地要求进行重复注解。

创建一个重复注解

如果一个注解在设计之初就是可重复的,你可以直接使用它。但是,如果你提供的注解是为用户提供的, 那么就需要做一些工作,说明该注解可以重复。下面是你需要执行的两个步骤:

  1. 将注解标记为@Repeatable
  2. 提供一个注解的容器下面的例子展示了如何将@Basic注解修改为可重复注解
@Repeatable(Basics.class)
@interface Basic {
    String name();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Basics {
    Basic[] value();
}

完成了这样的定义之后,Person类可以通过多个@Basic注解进行注释,如下所示:

@Basic(name="fix")
@Basic(name="todo")
class Person{ }

编译时, Person 会被认为使用了 @Basics( { @Basic(name=”fix”) , @Basic(name=”todo”)} ) 这样的形式进行了注解,所以,你可以把这种新的机制看成是一种语法糖, 它提供了程序员之前利用的惯用法类似的功能。为了确保与反射方法在行为上的一致性, 注解会被封装到一个容器中。 Java API中的getAnnotation(Class<T> annotationClass)方法会为注解元素返回类型为T的注解。 如果实际情况有多个类型为T的注解,该方法的返回到底是哪一个呢?

我们不希望一下子就陷入细节的魔咒,类Class提供了一个新的getAnnotationsByType方法, 它可以帮助我们更好地使用重复注解。比如,你可以像下面这样打印输出Person类的所有Basic注解:

返回一个由重复注解Basic组成的数组

public static void main(String[] args) {
    Basic[] basics = Person.class.getAnnotationsByType(Basic.class);
    Arrays.asList(basics).forEach(a -> {
        System.out.println(a.name());
    });
}

Null检查

Objects类添加了两个静态方法isNull和nonNull,在使用流的时候非常有用。

例如获取一个流的所有不为null的对象:

Stream.of("a", "c", null, "d")
        .filter(Objects::nonNull)
        .forEach(System.out::println);

 

原文地址:https://www.cnblogs.com/shamo89/p/8425851.html