Java8新特性——接口中的static,default方法

default方法

这些天在看ES6的语法,包括我以前学了一段时间的dart,这两门语言中都涉及到函数式编程,想想我对Java中的函数式编程还是不太了解,最近开始学习Java8的一些新特性,反正语言都差不多,一起学习好了。

在java8中新增了default方法,这个方法可以定义在接口中,其实就是在接口中定义了默认方法,这些默认方法可以在接口中就已经实现。

我看的是github上的Java8——tutorial,原文是英文的,其实理解起来不难。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface Formula {
double calculate(int a);

default double sqrt(int a){
return Math.sqrt(a);
}

static void main(String[] args) {
Formula formula = new Formula() {
@Override
public double calculate(int a) {
return a;
}
};
System.out.println(formula.calculate(5));
// 未实现也可以直接使用
System.out.println(formula.sqrt(5));
}
}

static方法

上面就已经定义了静态方法在接口中,在以往版本是不可以的。我们可以直接通过接口(不需要实现)来调用静态方法,但注意的是实现接口的类或者子接口(是继承不是实现)不会继承接口中的静态方法。

Lambda expressions

因为是跟着教程走的,涉及到的知识和教程的差不多,你们可以直接去原网站看。

我们可以使用lambda表达式改造上面的静态方法

1
2
3
4
5
static void main(String[] args) {
Formula formula = (a) -> a;
System.out.println(formula.calculate(5));
System.out.println(formula.sqrt(5));
}

能使用lambda表达式来实现的接口必须只能有一个抽象方法,然后我们写的那个lambda表达式会和原来类型中的抽象方法进行匹配。

这是原文(大概意思就是上面的话):

How does lambda expressions fit into Java’s type system? Each lambda corresponds to a given type, specified by an interface. A so called functional interface must contain exactly one abstract method declaration. Each lambda expression of that type will be matched to this abstract method. Since default methods are not abstract you’re free to add default methods to your functional interface.

然后我们可以在只有一个抽象方法的接口上面声明一个注解@FunctionalInterface来指明这个接口是一个函数接口,当我们尝试添加第二个抽象方法的时候编译器会报错。

We can use arbitrary interfaces as lambda expressions as long as the interface only contains one abstract method. To ensure that your interface meet the requirements, you should add the @FunctionalInterface annotation. The compiler is aware of this annotation and throws a compiler error as soon as you try to add a second abstract method declaration to the interface.

@FunctionalInterface

Method and Constructor References

方法和构造方法引用,Java 8允许您通过::关键字传递方法或构造函数的引用。

例子:

1
2
3
4
5
6
7
@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

我们可以使用::来化简代码

1
2
Converter<String, Integer> converter = Integer::valueof
// 可以这么理解本来我们可以将这个实现写成一个lambda表达式,这个表达式其实就是一个函数,我们现在只是要一个函数,然后我们通过方法引用吧方法赋值给它。这个方法必须参数返回值要相同

当然我们还可以使用某个实例化的对象的方法

1
2
3
4
5
6
7
8
class Something {
String startsWith(String s) {
return String.valueOf(s.charAt(0));
}
}

Something something = new Something();
Converter<String, String> converter = something::startsWith;

通过::引用构造器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person {
String firstName;
String lastName;

Person() {}

Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}

interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);
}

//我们通过构造器引用实现接口
PersonFactory<Person> pf = Person::new;
Person person = PersonFactory.create("11", "22");
-------------本文结束感谢阅读-------------