fundamentals\java\java8新特性-其他(译)

目录

 

更好的类型推断:Improved Type Inference

拓宽注解的应用场景:Type Annotations and Pluggable Type Systems

重复注解:Repeating Annotations

声明重复注解:Step 1: Declare a Repeatable Annotation Type

声明重复注解容器:Step 2: Declare the Containing Annotation Type

获得重复注解:Retrieving Annotations

注解设计:Design Considerations

获得参数名称:Method Parameter Reflection


Improved Type Inference

Improved Type Inference - The Java compiler takes advantage of target typing to infer the type parameters of a generic method invocation. The target type of an expression is the data type that the Java compiler expects depending on where the expression appears. For example, you can use an assignment statement's target type for type inference in Java SE 7. However, in Java SE 8, you can use the target type for type inference in more contexts. The most prominent example is using a method invocation's target types to infer the data types of its arguments.

改进的类型推断——Java编译器利用目标类型来推断泛型方法调用的类型参数。

表达式的目标类型是Java编译器期望的数据类型,这取决于表达式出现的位置。例如,你可以在Java SE 7中使用赋值语句的目标类型来进行类型推断。然而,在Java SE 8中,您可以在更多的上下文中使用目标类型来进行类型推断。最突出的例子是使用方法调用的目标类型来推断其参数的数据类型

// Consider the following example:考虑如下栗子

// Arrays.asList()的类型由编译器推导得出,不需要显式指明。在Java 7中这段代码会有编译错误

List<String> stringList = new ArrayList<>();

stringList.add("A");

stringList.addAll(Arrays.asList());

 

Disregarding generics for the moment, the method addAll expects a Collection instance as its argument, and the method Arrays.asList returns a List instance. This works because List is a subtype of Collection.

暂时不考虑泛型,方法addAll需求Collection实例作为它的参数,而方法Arrays.asList()返回一个List实例。这是可行的,因为List是集合的子类型

Now considering generics, the target type of addAll is Collection<? extends String>, and Arrays.asList returns a List<T> instance. In this example, the Java SE 8 compiler can infer that the value of the type variable T is String. The compiler infers this from the target type Collection<? extends String>.

现在考虑泛型,addAll 的目标类型是Collection<? extends String>,而 Arrays.asList 的返回值是 List<T> 实例。在本例中java8编译器能推断类型变量TString编译器从目标类型 Collection<? extends String>中推断出T的类型

 

Type Annotations and Pluggable Type Systems

Before the Java SE 8 release, annotations could only be applied to declarations. As of the Java SE 8 release, annotations can also be applied to any type use. This means that annotations can be used anywhere you use a type. A few examples of where types are used are class instance creation expressions (new), casts, implements clauses, and throws clauses. This form of annotation is called a type annotation and several examples are provided in Annotations Basics.

Java SE 8发布之前,注解只能应用于声明的类型上。在Java SE 8发行版中,注解也可以应用于任何类型的使用。(局部变量、接口类型、超类和接口实现类,甚至可以用在函数的异常定义上)

这意味着注解可以在任何使用类型的地方使用。一些使用类型的例子是类实例实例化表达式(new)、castimplementsthrows中。这种形式的注解称为类型注解,在注解基础上提供了几个示例。

// ElementType.TYPE_USERElementType.TYPE_PARAMETERJava 8新增的两个注解,用于描述注解的使用场景。

// Java 语言也做了对应的改变,以识别这些新增的注解

public class Annotations {

    @Retention( RetentionPolicy.RUNTIME )

    @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )

    public @interface NonEmpty {       

    }

 

    public static class Holder< @NonEmpty T > extends @NonEmpty Object {

        public void method() throws @NonEmpty Exception {           

        }

    }

 

    @SuppressWarnings( "unused" )

    public static void main(String[] args) {

        final Holder< String > holder = new @NonEmpty Holder< String >();       

        @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>();       

    }

}

 

 

Type annotations were created to support improved analysis of Java programs way of ensuring stronger type checking. The Java SE 8 release does not provide a type checking framework, but it allows you to write (or download) a type checking framework that is implemented as one or more pluggable modules that are used in conjunction with the Java compiler.

类型注解的创建是为了支持对Java程序的改进分析,以确保更强的类型检查。

Java SE 8版本不提供类型检查框架,但是它允许您编写(或下载)类型检查框架,该框架是作为一个或多个可插入模块实现的,这些模块与Java编译器一起使用。

 

For example, you want to ensure that a particular variable in your program is never assigned to null; you want to avoid triggering a NullPointerException. You can write a custom plug-in to check for this. You would then modify your code to annotate that particular variable, indicating that it is never assigned to null. The variable declaration might look like this:

@NonNull String str;

例如,您想要确保程序中的某个特定变量永远不会被赋值为null;您希望避免触发NullPointerException

您可以编写一个定制的插件来检查这个。然后您将修改您的代码来注解那个特定的变量,表明它从来没有被赋值为null。变量声明可能是这样的:

 

When you compile the code, including the NonNull module at the command line, the compiler prints a warning if it detects a potential problem, allowing you to modify the code to avoid the error. After you correct the code to remove all warnings, this particular error will not occur when the program runs.

当您编译代码时,包括命令行中的NonNull模块,如果它检测到一个潜在的问题,编译器会打印一个警告,允许您修改代码以避免错误。在您纠正了删除所有警告的代码之后,这个特定的错误将不会在程序运行时发生。

 

You can use multiple type-checking modules where each module checks for a different kind of error. In this way, you can build on top of the Java type system, adding specific checks when and where you want them.

您可以使用多个类型检查模块,其中每个模块检查不同类型的错误。通过这种方式,您可以构建在Java类型系统之上,在您需要的时间和地点添加特定的检查。

 

With the judicious use of type annotations and the presence of pluggable type checkers, you can write code that is stronger and less prone to error.

通过明智地使用类型注解和可插入式检查器的存在,您可以编写更强、更不容易出错的代码。

 

In many cases, you do not have to write your own type checking modules. There are third parties who have done the work for you. For example, you might want to take advantage of the Checker Framework created by the University of Washington. This framework includes a NonNull module, as well as a regular expression module, and a mutex lock module. For more information, see the Checker Framework.

在许多情况下,您不必编写自己的类型检查模块。有第三方为你做了这项工作。例如,您可能想要利用由华盛顿大学创建的检查器框架。这个框架包括一个非空模块,以及一个正则表达式模块和一个互斥锁模块。要了解更多信息,请参见Checker Framework.

Repeating Annotations

 There are some situations where you want to apply the same annotation to a declaration or type use. As of the Java SE 8 release, repeating annotations enable you to do this.

在某些情况下,您希望将相同的注解应用于声明或类型使用。在Java SE 8发行版中,重复注解使您能够做到这一点

For example, you are writing code to use a timer service that enables you to run a method at a given time or on a certain schedule, similar to the UNIX cron service. Now you want to set a timer to run a method, doPeriodicCleanup, on the last day of the month and on every Friday at 11:00 p.m. To set the timer to run, create an @Schedule annotation and apply it twice to the doPeriodicCleanup method. The first use specifies the last day of the month and the second specifies Friday at 11p.m., as shown in the following code example:

例如,您正在编写代码来使用定时器服务,它使您能够在给定的时间或特定的调度中运行一个方法,类似于UNIX cron服务。现在,您需要设置一个计时器来运行一个方法,doPeriodicCleanup,在每个月的最后一天,以及每个周五晚上11:00。要设置定时器来运行,创建一个@schedule注释,并将它应用两次到doPeriodicCleanup方法。第一个使用指定了本月的最后一天,第二个使用指定星期五为11p.m。如下面的代码示例所示

// 创建一个@schedule注释,并将它应用两次到doPeriodicCleanup方法。

// 第一个使用指定了本月的最后一天,第二个使用指定星期五为11p.m

@Schedule(dayOfMonth="last")

@Schedule(dayOfWeek="Fri", hour="23")

public void doPeriodicCleanup() { ... }

 

The previous example applies an annotation to a method. You can repeat an annotation anywhere that you would use a standard annotation. For example, you have a class for handling unauthorized access exceptions. You annotate the class with one @Alert annotation for managers and another for admins:

前面的例子对一个方法应用了一个注解。使用标准注解您可以在任何地方重复注解。例如,您有一个用于处理未授权访问异常的类。您可以为部门经理使用一个@alert注解,为管理员使用另一个@alert注解:

@Alert(role="Manager")
@Alert(role="Administrator")
public class UnauthorizedAccessException extends SecurityException { ... }

 

For compatibility reasons, repeating annotations are stored in a container annotation that is automatically generated by the Java compiler. In order for the compiler to do this, two declarations are required in your code.

出于兼容性的考虑,重复注解存储在由Java编译器自动生成的注解容器中。为了让编译器做到这一点,您的代码中需要两个声明

Step 1: Declare a Repeatable Annotation Type

// The annotation type must be marked with the @Repeatable meta-annotation.

// The following example defines a custom @Schedule repeatable annotation type:

// 使用 @Repeatable标注注解

@Repeatable(Schedules.class)

public @interface Schedule {

  String dayOfMonth() default "first";

  String dayOfWeek() default "Mon";

  int hour() default 12;

}

 

The value of the @Repeatable meta-annotation, in parentheses, is the type of the container annotation that the Java compiler generates to store repeating annotations. In this example, the containing annotation type is Schedules, so repeating @Schedule annotations is stored in an @Schedules annotation.

在括号中,@Repeatable 元注释的值是Java编译器生成的用来储存重复注解的容器的类。在这个例子中,包含注解类型是日程安排,因此重复@schedule注解存储在@schedule的注解中

Applying the same annotation to a declaration without first declaring it to be repeatable results in a compile-time error.

@Repeatable声明可重复的, 使用将相同的注解到声明中,在编译时会报错。

Step 2: Declare the Containing Annotation Type

The containing annotation type must have a value element with an array type. The component type of the array type must be the repeatable annotation type. The declaration for the Schedules containing annotation type is the following:

容器注解类型必须有一个带有数组类型的value元素。数组的类型必须是可重复的注解类型。容器注解Schedules 的声明如下

// Schedule必须是可重复注解@Repeatable 标注的类型

public @interface Schedules {

    Schedule[] value();

}

 

 

Retrieving Annotations

There are several methods available in the Reflection API that can be used to retrieve annotations. The behavior of the methods that return a single annotation, such as AnnotatedElement.getAnnotation(Class<T>), are unchanged in that they only return a single annotation if one annotation of the requested type is present. If more than one annotation of the requested type is present, you can obtain them by first getting their container annotation. In this way, legacy code continues to work. Other methods were introduced in Java SE 8 that scan through the container annotation to return multiple annotations at once, such asAnnotatedElement.getAnnotationsByType(Class<T>). See the AnnotatedElement class specification for information on all of the available methods.

反射API中有几种检索注解的方法。这些方法返回单个注解,如注解元素. AnnotatedElement.getAnnotationClass),没有变动,因为当类型的注解存在时,它只返回单个注解。如果类型有多个注解,您可以通过首先获得它们的容器注释来获得它们。通过这种方式,以上的代码继续生效。其他方法是在Java SE 8中引入的,它可以扫描容器注释,同时返回多个注释。比如; AnnotatedElement.getAnnotationsByType(Class<T>),参考AnnotatedElement

Design Considerations

When designing an annotation type, you must consider the cardinality of annotations of that type. It is now possible to use an annotation zero times, once, or, if the annotation's type is marked as @Repeatable, more than once. It is also possible to restrict where an annotation type can be used by using the @Target meta-annotation. For example, you can create a repeatable annotation type that can only be used on methods and fields. It is important to design your annotation type carefully to ensure that the programmer using the annotation finds it to be as flexible and powerful as possible.

在设计注解类型时,您必须考虑这种类型的注解的基数。现在可以使用注释0次,一次,或者不止一次,如果注解的类型被标记为@Repeatable。也可以限制使用@target元注释可以使用注解类型的地方。例如,您可以创建一个可重复的注解类型,只能在方法和字段上使用。仔细设计注解类型是很重要的,以确保使用注解的程序员发现它尽可能的灵活和强大。

Method Parameter Reflection

You can obtain the names of the formal parameters of any method or constructor with the method java.lang.reflect.Executable.getParameters. (The classes Method and Constructor extend the class Executable and therefore inherit the method Executable.getParameters.) However, .class files do not store formal parameter names by default. To store formal parameter names in a particular .class file, and thus enable the Reflection API to retrieve formal parameter names, compile the source file with the -parameters option of the javac compiler. See Obtaining Names of Method Parameters in the Java Tutorials.

您可以使用java.lang.reflect.Executable.getParameters.获得任何方法或构造器的正式参数的名称。然而, class文件默认不存储正式的参数名。将正式的参数名称存储在特定的名称中class文件,从而使反射API能够检索正式的参数名,用javac编译器的-parameters 选项编译源文件参考:Obtaining Names of Method Parameters 文档。

猜你喜欢

转载自blog.csdn.net/u012296499/article/details/81778164