本帖最后由 tuan2016 于 2016-5-15 00:15 编辑
2.5 更好的类型推测机制Java 8在类型推测方面有了很大的提高。在很多情况下,编译器可以推测出确定的参数类型,这样就能使代码更整洁。让我们看一个例子: - package com.javacodegeeks.java8.type.inference;
- public class Value< T > {
- public static< T > T defaultValue() {
- return null;
- }
-
- public T getOrDefault( T value, T defaultValue ) {
- return ( value != null ) ? value : defaultValue;
- }
- }
复制代码
这里是Value< String >类型的用法。 - package com.javacodegeeks.java8.type.inference;
- public class TypeInference {
- public static void main(String[] args) {
- final Value< String > value = new Value<>();
- value.getOrDefault( "22", Value.defaultValue() );
- }
- }
复制代码
Value.defaultValue()的参数类型可以被推测出,所以就不必明确给出。在Java 7中,相同的例子将不会通过编译,正确的书写方式是 Value.< String >defaultValue()。
2.6 扩展注解的支持Java 8扩展了注解的上下文。现在几乎可以为任何东西添加注解:局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解。下面演示几个例子: - package com.javacodegeeks.java8.annotations;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- import java.util.ArrayList;
- import java.util.Collection;
- 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<>();
- }
- }
复制代码
ElementType.TYPE_USE和ElementType.TYPE_PARAMETER是两个新添加的用于描述适当的注解上下文的元素类型。在Java语言中,注解处理API也有小的改动来识别新增的类型注解。
3. Java编译器的新特性
3.1 参数名字很长一段时间里,Java程序员一直在发明不同的方式使得方法参数的名字能保留在Java字节码中,并且能够在运行时获取它们(比如,Paranamer类库)。最终,在Java 8中把这个强烈要求的功能添加到语言层面(通过反射API与Parameter.getName()方法)与字节码文件(通过新版的javac的–parameters选项)中。 - package com.javacodegeeks.java8.parameter.names;
- import java.lang.reflect.Method;
- import java.lang.reflect.Parameter;
- public class ParameterNames {
- public static void main(String[] args) throws Exception {
- Method method = ParameterNames.class.getMethod( "main", String[].class );
- for( final Parameter parameter: method.getParameters() ) {
- System.out.println( "Parameter: " + parameter.getName() );
- }
- }
- }
复制代码
如果不使用–parameters参数来编译这个类,然后运行这个类,会得到下面的输出:
如果使用–parameters参数来编译这个类,程序的结构会有所不同(参数的真实名字将会显示出来):
对于有经验的Maven用户,通过maven-compiler-plugin的配置可以将-parameters参数添加到编译器中去。 - <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
- <configuration>
- <compilerArgument>-parameters</compilerArgument>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
复制代码
针对Java 8最新发布的Eclipse Kepler SR2(请检查这里的下载说明)提供了非常实用的配置选项,可以通过下图的配置方式来控制编译器行为
图1. 配置Eclipse工程使之支持Java 8编译器的新特性——parameters参数此外,Parameter类有一个很方便的方法isNamePresent()来验证是否可以获取参数的名字。
|