接口的增强
在1.8版本后,接口允许有默认方法(JDK1.8)、静态方法(JDK1.8)、私有方法(JDK1.9)
静态方法
定义一个接口Task
public interface Task {
void run();//1.8之前只能定义抽象方法
static void doSomething(){
IO.println("接口静态方法调用");
}
}
创建一个测试类
public class Test {
static void main() {
Task.doSomething();//使用接口调用静态方法
}
}
默认方法
默认方法只能在他的实现类中调用
修改Task接口
public interface Task {
void run();//1.8之前只能定义抽象方法
//静态方法
static void doSomething(){
IO.println("接口静态方法调用");
}
//默认方法:只能在他的实现类中调用
default void fun1(){
IO.println("接口默认方法调用");
}
}
新建一个实现类MyTask:将接口中的默认方法直接集成到实现类中
public class MyTask implements Task{
public void run() {
fun1();//调用接口类中定义的默认方法,将接口中的默认方法直接集成到实现类中
IO.println("子类run方法");
}
}
测试类:
public class Test {
static void main() {
// Task.doSomething();//使用接口调用静态方法
MyTask myTask = new MyTask();
myTask.run();
myTask.fun1();
}
}
私有方法
私有方法不会被继承,只会被default使用
public interface Task {
void run();//1.8之前只能定义抽象方法
//私有方法
private void a(){
IO.println("私有方法调用");
}
}

函数式接口
只有一个抽象方法的接口,就叫函数式接口;默认方法,静态方法,私有方法,无效的抽象方法,都不计入统计,可以在有一个抽象方法的情况下定义这些方法,这个接口仍然是函数式接口。
注解@FunctionalInterface用于指定一个接口是函数式接口(可以不加注解,加了注解就只能定义一个方法)。
函数式接口用于实现(部分实现)函数式编程范式(函数式编程没有线程安全问题,天生对线程安全免疫)。
Lambda表达式
特点:定义的时候没有函数名称
将接口引用指向一个lambda表达式(这个接口必须是一个函数式接口,否则不能使用lambda表达式)

圈起来的部分是Lambda表达式
参数列表必须是和函数式接口的参数相同,否则会报错
注意事项:
- 如果函数式接口中的sam(抽象方法)没有参数的话,则必须写小括号;
- 如果函数式接口有多个参数的话,则lambda表达式完整写法是和原函数定义一致;


- lambda表达式可以省略参数的类型(要没有参数类型都没有参数类型,不能一些写参数类型一些不写);
- 如果有多个参数(不包括1个),小括号不能省略;
- 特殊情况:如果只有一个参数,则小括号可以省略;
static void main(){ Task t = a -> { IO.println("你好"); }; } - 如果方法题有0条语句或多条语句,则大括号不能省略;
- 如果方法体只有1条语句,则大括号可以省略(参考IF语句);
- 特殊的,如果方法题只有1条语句,return必须省略;
@FunctionalInterface public interface Task { int run(int a); }public class test { static void main(){ Task t = a -> 10; } }如果一定要使用return则需要加大括号。
常用的函数式接口
java.util.function
| 抽象方法 | 典型用途 | |
|---|---|---|
Consumer<T> |
void accept(T t) |
消费一个值,不返回结果 |
Supplier<T> |
T get() |
提供一个值 |
Function<T, R> |
R apply(T t) |
把 T 转换成 R |
Predicate<T> |
boolean test(T t) |
//消费者:只有参数没有返回值
Consumer<Integer> consumer = t -> IO.println(t);
//供应者:只有返回值没有参数
Supplier<Integer> supplier = () -> 100;
//函数:既有返回值又有参数
Function<Integer, Double> function = t -> Math.pow(t,2);
//断言:接收一个参数返回一个boolean类型
Predicate<Integer> predicate = t -> t%2 == 0 ;
方法引用
引用的方法的返回值和参数列表必须和对应的函数式接口的返回值和参数列表匹配
public interface Task {
void action(String s);
}
public class test {
static void main() {
Task t = IO::println;//方法引用
t.action("你好");
}
}
对比一下lambda表达式和方法引用的区别,创建一个StringHander函数式接口
@FunctionalInterface
public interface StringHander {
String handle(String s1);
}
先使用lambda表达式处理字符串:
public class test {
static void main() {
StringHander s1 = it -> it.toUpperCase();
String result = s1.handle("abcdef");
IO.println(result);
}
}
再看使用方法引用处理字符串:
public class test {
static void main() {
StringHander s2 = String::toUpperCase;
String result = s2.handle("abcdef");
IO.println(result);
}
}
THE END



暂无评论内容