Lambda表达式深度解析(3)

Lambda表达式深度解析(3)

一、接口函数重载解析

我们都知道java方法可以重载,重载的定义:接口名称相同,参数列表不同。

1.1 那么如果两个方法的入参都是lambda表达式呢? 并且这个时候重载的方法参数为,继承关系的时候呢?

示例:

package com.jiangdeen.lambda.day03;

import java.util.function.BinaryOperator;

public interface IntegerBiFunction extends BinaryOperator<Integer> {
}


// ------------------------------------test-------------------------------------------
package com.jiangdeen.lambda.day03;

import java.util.function.BiFunction;
import java.util.function.BinaryOperator;

public class Test3 {

    private void overloadedMethod(BinaryOperator<Integer> lambda) {
        System.out.println("binaryOperator");
    }

    private void overloadedMethod(IntegerBiFunction lambda) {
        System.out.println("biFunction");
    }

    public static void main(String[] args) {
        Test3 t3 = new Test3();
        t3.overloadedMethod((a, b) -> a + b);
    }
}

自定义IntegerBiFunction类,并且继承BinaryOperator, 相当于这两个类都是接口函数重载两个函数,直接使用lambda表达式调用这两个函数.

大家来猜猜是什么结果?

image-20240611072048424

从编译上就可以看出结果,调用的是子类方法,由此我们得出一个重要结论,如果重载入参为lambda表达式的方法,那么在使用lambda表达式调用的时候,子类优先父类

1.2 如果重载的方法入参,都是接口函数,但是参数之间不存在继承关系,会是什么情况呢?

package com.jiangdeen.lambda.day03;

/**
 * 测试lambda 重载机制
 */
public interface MyPredicate<T> {

    boolean test(T t);
}


    /**
     * 重载的两个方法,入参没有关系,但是都是接口函数
     *
     * @param lambda
     */
    private void overloadedMethod01(Predicate<Integer> lambda) {
        System.out.println("Predicate");
    }

    private void overloadedMethod01(MyPredicate<Integer> lambda) {
        System.out.println("MyPredicate");
    }

    public static void main(String[] args) {
        Test3 t3 = new Test3();
        t3.overloadedMethod((a, b) -> a + b);
        t3.overloadedMethod01(a -> a > 7);
    }

image-20240611073336460

在这种情况下,编译就会报错,提示调用不明确,二者都可以. 这里我们又得出一个重要结论: 当重载方法的入参都是接口函数,并且两个入参之间没有继承关系时,使用lambda表达式构造入参会提示编译错误

那么在这种情况下想要实现调用,必须指定类型 例如:t3.overloadedMethod01((MyPredicate<Integer>) a -> a > 7);

二、@FunctionalInterface 注解

@FunctionalInterface 注解用于指定一个接口是否是接口函数,事实上如果被当做接口函数使用的接口都要加上这个注解,加上这注解的好处是,如果在接口函数中又添加了新的抽象方法,那么就会提示编译错误.

image-20240611074606402

三、接口默认方法

不知道你有没有注意到,java8接口新增了默认方法, 在接口中用default来进行声明.

Collection接口中增加了心得Stream方法,如何才能让用户的 自定义List 在不知道该方法的情况下通过编译? java8通过如下方法解决该问题:

Collection接口告诉它所有的子类:如果你没有实现Stream方法,就使用我的吧. 接口中这样的方法叫做默认方法,在任何接口中,无论是函数接口还是非函数接口,都可以使用该方法.

定义父类:

package com.jiangdeen.lambda.day03;

public interface Parent {

    void message(String body);

    default void welcome() {
        message("parent");
    }

    String getLastMessage();
}

字类重写父类默认方法:

package com.jiangdeen.lambda.day03;

public interface Child extends Parent {

    @Override
    default void welcome() {
        message("Child");
    }

}

测试默认方法优先级:

package com.jiangdeen.lambda.day03;

/**
 * 默认方法测试类
 */
public class DefaultTest {

    public static void main(String[] args) {
        test1();
        test2();
    }

      /**
     * 默认方法测试
     */
    private static void test1() {
        Parent parent = new ParentImpl();
        parent.welcome();
    }

    private static void test2() {
        Child child = new ChildImpl();
        child.welcome();
    }

    private static void test3() {
        Child child = new OverridingChild();
        child.welcome();
    }
}

最终我们看到,子类中的方法优先于父类当中的默认方法.

3.1 默认方法的多重继承
package com.jiangdeen.lambda.day03;

public interface Carriage {
    default String rock() {
        return "Carriage.rock";
    }
}
// -----------------------------------------------------------------------
package com.jiangdeen.lambda.day03;

public interface Jukebox {
    default String rock() {
        return "Jukebox.rock";
    }
}

// -------------------------------------------------------------------------
public class MusicalCarriage implements Carriage,Jukebox{
}

image-20240611084018935

一个类实现了两个接口,两个接口中有相同的默认方法, 按照道理来说,默认方法是不会强制重写的,但是这个时候,java编译器会提示我们需要强制重写,不然编译无法通过.

四、接口当中静态方法

接口当中的静态方法也是java8当中添加的新特性,一般情况下,我们会把包含了很多静态代码块的方法整理成一个工具类,如果一个方法有充分的语义原因和某个概念强相关,那么就可以放在接口中.

GitHub地址: 如果喜欢给个start;

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值