默认方法
可以给接口添加一个默认的实现方法,优点,针对现有的接口,如List
,我们可以偷偷
的添加新的方法,这样可以达到一种兼容目的
实例
public interface A {
default void print() {
System.out.println("A.print()");
}
}
public interface B {
default void print() {
System.out.println("B.print()");
}
}
C类直接实现默认接口
public class C implements A, B {
// 这里的重写是因为方法冲突,正常情况是不需要重写的
@Override
public void print() {
A.super.print();
B.super.print();
}
public static void main(String[] args) {
A a = new C();
a.print();
}
}
默认方法还有一个好处就是给一个现有类添加一个方法十分方便,直接implements
即可
静态默认方法
使用上与嵌套类相似,可做工具类使用
定义
public interface D {
public static void print() {
System.out.println("D.print()");
}
}
使用
public class DTest {
public static void main(String[] args) {
D.print();
}
}
Lambda 表达式
将函数作为参数传递进方法中
例子一
定义一个接口,实现接口
public interface Calc {
String operate(int x, int y);
}
public class CalcImpl implements Calc {
@Override
public String operate(int x, int y) {
return x + y + " - end";
}
}
使用接口
public class Controller {
public void print(int x, int y) {
Calc calc = new CalcImpl();
String result = calc.operate(x, y);
System.out.println("start - " + result);
}
}
测试接口
public class TestRun {
public static void main(String[] args) {
Controller controller = new Controller();
controller.print(10, 20);
}
}
上述接口使用与实现绑定,高耦合,改造一下代码
例子二
将接口当做入参传入
public class Controller {
public void print(int x, int y, Calc calc) {
String result = calc.operate(x, y);
System.out.println("start - " + result);
}
}
测试代码,将具体的实现逻辑放入使用方法之外,这样如果有新的计算,可以实现热绑定,低耦合
public class TestRun {
public static void main(String[] args) {
Calc calc = new CalcImpl();
Controller controller = new Controller();
controller.print(10, 20, calc);
}
}
例子三
匿名内部类的引用,重新实现一种计算方法
public class TestRun {
public static void main(String[] args) {
Calc calc = new Calc() {
@Override
public String operate(int x, int y) {
return x + y + "";
}
};
Controller controller = new Controller();
controller.print(10, 20, calc);
}
}
以上代码也等价于下面代码
public class TestRun {
public static void main(String[] args) {
Controller controller = new Controller();
controller.print(10, 20, new Calc() {
@Override
public String operate(int x, int y) {
return x + y + "";
}
});
}
}
像new Calc
,operate
等信息我们可以去掉,这时,我们可以引入Lambda 表达式。简化如下
public class TestRun {
public static void main(String[] args) {
Controller controller = new Controller();
controller.print(10, 20, (int x, int y) -> {
return x + y + "";
}
);
}
}
甚至我们还可以把入参类型
,返回关键字return
去掉,如下
public class TestRun {
public static void main(String[] args) {
Controller controller = new Controller();
controller.print(10, 20, (x,y) -> x + y + "");
}
}
语法
lambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
注意点一,Lambda定义一个接口只允许有一个方法,定义超过一个使用Lambda接口会提示错误,如下所示
public interface Calc {
String operate(int x, int y);
void print();
}
可强制约束定义,加上@FunctionalInterface
注解生声明定义
@FunctionalInterface
public interface Calc {
String operate(int x, int y);
}
方法引用
方法引用是将方法传入给lambda方法,可支持以下三种
- 构造器
- 对象方法
- 静态方法
定义一个类
public class Deal {
public void repair() {
System.out.println("Repaired ");
}
public void repair2222() {
System.out.println("Repaired 2222");
}
public void repair6666() {
System.out.println("Repaired 6666");
}
}
定义两个函数式接口参数,其中Consumer
,Supplier
都是JDK提供的
public class MyTest {
public void doTryClass(Consumer<Deal> action) {
Deal deal = new Deal();
action.accept(deal);
}
public void doTryClass(Supplier<Deal> supplier) {
Deal deal = supplier.get();
deal.repair();
}
}
静态调用
public class DealStatic {
public static void saymmp(Deal deal) {
System.out.println("===");
deal.repair6666();
System.out.println("===");
}
}
调用测试
public class OtherTest {
public static void main(String[] args) {
MyTest test = new MyTest();
// 消费自身的方法可以不传参数
test.doTryClass(Deal::repair);
test.doTryClass(Deal::repair2222);
test.doTryClass(Deal::repair6666);
// 静态方法(传入参数必须与Consumer泛型参数Deal一致)
test.doTryClass(DealStatic::saymmp);
// 非静态方法需要先实例化,再引用
DealNonStatic nonDeal = new DealNonStatic();
test.doTryClass(nonDeal::test);
// 构造器
test.doIt4getClass(Deal::new);
}
}
测试结果
Repaired
Repaired 2222
Repaired 6666
===
Repaired 6666
===
===non
Repaired 6666
===non
Repaired
java 8 提供的函数式接口列表
以下仅供参考
函数式接口 | 描述 |
---|---|
BiConsumer<T,U> | 代表了一个接受两个输入参数的操作,并且不返回任何结果 |
BiFunction<T,U,R> | 代表了一个接受两个输入参数的方法,并且返回一个结果 |
BinaryOperator<T> | 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
BiPredicate<T,U> | 代表了一个两个参数的boolean值方法 |
BooleanSupplier | 代表了boolean值结果的提供方 |
Consumer<T> | 代表了接受一个输入参数并且无返回的操作 |
DoubleBinaryOperator | 代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
DoubleConsumer | 代表一个接受double值参数的操作,并且不返回结果。 |
DoubleFunction<R> | 代表接受一个double值参数的方法,并且返回结果 |
DoublePredicate | 代表一个拥有double值参数的boolean值方法 |
DoubleSupplier | 代表一个double值结构的提供方 |
DoubleToIntFunction | 接受一个double类型输入,返回一个int类型结果。 |
DoubleToLongFunction | 接受一个double类型输入,返回一个long类型结果 |
DoubleUnaryOperator | 接受一个参数同为类型double,返回值类型也为double 。 |
Function<T,R> | 接受一个输入参数,返回一个结果。 |
IntBinaryOperator | 接受两个参数同为类型int,返回值类型也为int 。 |
IntConsumer | 接受一个int类型的输入参数,无返回值 。 |
IntFunction<R> | 接受一个int类型输入参数,返回一个结果 。 |
IntPredicate | :接受一个int输入参数,返回一个布尔值的结果。 |
IntSupplier | 无参数,返回一个int类型结果。 |
IntToDoubleFunction | 接受一个int类型输入,返回一个double类型结果 。 |
IntToLongFunction | 接受一个int类型输入,返回一个long类型结果。 |
IntUnaryOperator | 接受一个参数同为类型int,返回值类型也为int 。 |
LongBinaryOperator | 接受两个参数同为类型long,返回值类型也为long。 |
LongConsumer | 接受一个long类型的输入参数,无返回值。 |
LongFunction<R> | 接受一个long类型输入参数,返回一个结果。 |
LongPredicate | R接受一个long输入参数,返回一个布尔值类型结果。 |
LongSupplier | 无参数,返回一个结果long类型的值。 |
LongToDoubleFunction | 接受一个long类型输入,返回一个double类型结果。 |
LongToIntFunction | 接受一个long类型输入,返回一个int类型结果。 |
LongUnaryOperator | 接受一个参数同为类型long,返回值类型也为long。 |
ObjDoubleConsumer<T> | 接受一个object类型和一个double类型的输入参数,无返回值。 |
ObjIntConsumer<T> | 接受一个object类型和一个int类型的输入参数,无返回值。 |
ObjLongConsumer<T> | 接受一个object类型和一个long类型的输入参数,无返回值。 |
Predicate<T> | 接受一个输入参数,返回一个布尔值结果。 |
Supplier<T> | 无参数,返回一个结果。 |
ToDoubleBiFunction<T,U> | 接受两个输入参数,返回一个double类型结果 |
ToDoubleFunction<T> | 接受一个输入参数,返回一个double类型结果 |
ToIntBiFunction<T,U> | 接受两个输入参数,返回一个int类型结果。 |
ToIntFunction<T> | 接受一个输入参数,返回一个int类型结果。 |
ToLongBiFunction<T,U> | 接受两个输入参数,返回一个long类型结果。 |
ToLongFunction<T> | 接受一个输入参数,返回一个long类型结果。 |
UnaryOperator<T> | 接受一个参数为类型T,返回值类型也为T。 |