方法引用使得开发者能够直接引用现存的方法、Java类的构造方法或者实例对象。方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有不少复杂的模板代码。html
方法引用包括几种状况:java
例子中,Car类是不一样方法引用的例子,能够帮助读者区分四种类型的方法引用。oracle
package com.study.demo.TestRefernce; import java.util.Arrays; import java.util.List; import java.util.function.Supplier; public class Car { private String name ="I am a car"; @Override public String toString() { return "Car{" + "name='" + name + '\'' + '}'; } public static Car create(final Supplier< Car > supplier ) { return supplier.get(); } public static void collide( Car car ) { System.out.println( "Collided " + car.toString() ); } public void follow( Car another ) { System.out.println( "Following the " + another.toString() ); } public void repair() { System.out.println( "Repaired " + this.toString() ); } public static void main(String[] args) { final Car car = Car.create(Car::new); final List< Car > cars = Arrays.asList( car ,Car.create(Car::new)); cars.forEach(Car::collide ); cars.forEach(Car::repair); final Car car1 = Car.create(Car::new); cars.forEach(car1::follow); } }
final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car );
cars.forEach( Car::collide );
cars.forEach( Car::repair );
也能够这样:框架
cars.forEach(c -> c.repair());
final Car police = Car.create(Car::new); cars.forEach((car1) -> police.follow(car1));
final Car police = Car.create( Car::new ); cars.forEach( police::follow );
运行上述例子,能够在控制台看到以下输出(Car实例可能不一样):ide
自从Java 5中引入注解以来,这个特性开始变得很是流行,并在各个框架和项目中被普遍使用。不过,注解有一个很大的限制是:在同一个地方不能屡次使用同一个注解。Java 8打破了这个限制,引入了重复注解的概念,容许在同一个地方屡次使用同一个注解。函数
在Java 8中使用@Repeatable注解定义重复注解,实际上,这并非语言层面的改进,而是编译器作的一个trick,底层的技术仍然相同。能够利用下面的代码说明。学习
import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class RepeatingAnnotations { @Target( ElementType.TYPE ) @Retention( RetentionPolicy.RUNTIME ) public @interface Filters { Filter[] value(); } @Target( ElementType.TYPE ) @Retention( RetentionPolicy.RUNTIME ) @Repeatable( Filters.class ) public @interface Filter { String value(); }; @Filter( "filter1" ) @Filter( "filter2" ) public interface Filterable { } public static void main(String[] args) { for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) { System.out.println( filter.value() ); } } }
正如咱们所见,这里的Filter类使用@Repeatable(Filters.class)注解修饰,而Filters是存放Filter注解的容器,编译器尽可能对开发者屏蔽这些细节。这样,Filterable接口能够用两个Filter注解注释(这里并无提到任何关于Filters的信息)。this
另外,反射API提供了一个新的方法:getAnnotationsByType(),能够返回某个类型的重复注解,例如Filterable.class.getAnnoation(Filters.class)
将返回两个Filter实例,输出到控制台的内容以下所示:spa
filter1 filter2
若是你但愿了解更多内容,能够参考官方文档。code
Java 8编译器在类型推断方面有很大的提高,在不少场景下编译器能够推导出某个参数的数据类型,从而使得代码更为简洁。例子代码以下:
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>类型的应用:
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()
。
Java 8新增的两个注解:
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<>(); } }