文章概览
- 默认接口方法
- Lambda表达式
- 方法引用
- 重复注解
简单介绍
接口中有默认方法
@FunctionalInterface
interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
注意:
//接口前加上@FunctionalInterface 标注,方便使用lambda
//加这个注解,java可以很好的向下兼容jdk的版本
//如果你不写@FunctionalInterface 标注,程序也是正确的。
默认方法是为了实现函数式编程,lambda表达式
“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted); // 123
lamdba格式:
(参数列表)->{ 方法体}
():跟元方法参数一致,都是小括号抱住
{}:方法体,跟原来方法一致,都是大括号抱住
-> :箭头,连接方法参数和方法体,表示一个函数
方法参数为一个时,小括号可以省略不写
方法体为一行代码时,大括号可以省略不写
lamdba在java中本质是一个静态方法,java编译成方法。
lamdba表达式可以简写为方法引用。
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted); // 123
通过::关键字获取方法或者构造函数的的引用
引用构造函数
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");
通过Person::new来创建一个Person类构造函数的引用。Java编译器会自动地选择合适的构造函数来匹配PersonFactory.create函数的签名,并选择正确的构造函数形式。
Lambda的范围
对于lambdab表达式外部的变量,其访问权限的粒度与匿名对象的方式非常类似。你能够访问局部对应的外部区域的局部final变量,以及成员变量和静态变量。
但是与匿名对象不同的是,变量num并不需要一定是final,num在编译的时候被隐式地当做final变量来处理。下面的代码依然是合法的:
int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num);
stringConverter.convert(2); // 3
java8中内置了很多函数式接口
具体的查看官方文档
简单示例如下:
遍历map
map.forEach((k, v) -> System.out.println(v));
遍历list
list.forEach((m) -> System.out.println(m));
Annotations 重复注解
Java 8中的注解是可重复的。让我们直接深入看看例子,弄明白它是什么意思。
首先,我们定义一个包装注解,它包括了一个实际注解的数组
@interface Hints {
Hint[] value();
}
@Repeatable(Hints.class)
@interface Hint {
String value();
}
只要在前面加上注解名:@Repeatable,Java 8 允许我们对同一类型使用多重注解,
变体1:使用注解容器(老方法)
@Hints({@Hint("hint1"), @Hint("hint2")})
class Person {}
变体2:使用可重复注解(新方法)
@Hint("hint1")
@Hint("hint2")
class Person {}
使用变体2,Java编译器能够在内部自动对@Hint进行设置。这对于通过反射来读取注解信息来说,是非常重要的。
Hint hint = Person.class.getAnnotation(Hint.class);
System.out.println(hint); // null
Hints hints1 = Person.class.getAnnotation(Hints.class);
System.out.println(hints1.value().length); // 2
Hint[] hints2 = Person.class.getAnnotationsByType(Hint.class);
System.out.println(hints2.length); // 2
尽管我们绝对不会在Person类上声明@Hints注解,但是它的信息仍然可以通过getAnnotation(Hints.class)来读取。并且,getAnnotationsByType方法会更方便,因为它赋予了所有@Hints注解标注的方法直接的访问权限。
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@interface MyAnnotation {}
详细看这里:http://blog.didispace.com/books/java8-tutorial/ch1.html