Java 8 简明教程

文章概览

  • 默认接口方法
  • 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

上一篇:JAVA集合框架


下一篇:从web开发看.NET和Java。