Lambda 表达式(2)

Lambda 表达式(2)

接口的组成更新

​ 接口的组成

  • 常量

接口中常量默认是 public static final 这些是可以省略的

  • 抽象方法

    接口中方法默认是 public abstract 这些是可以省略的

  • 默认方法(java8)

  • 静态方法(java8)

  • 私有方法(java9)

默认方法(java8)

在出现默认方法之前,实现类必须实现接口的每一个方法,那么如果一个接口的实现类很多,但是有的实现类并不需要实现某些方法的时候,静态方法就有了用处。

例如:定义接口并且有两个普通方法和一个默认方法。

默认方法必须加default 关键字

public interface InterTest {
    void test();
    void test1();

    default void test2(){
        //todo 此处写接口默认的方法,如果实现类不重写的话,会默认走此内容
    }
}

实现类:

两个普通的方法,实现类中必须实现,但是默认方法可以选择实现

public class InterTestImpl1 implements InterTest {
    @Override
    public void test() {
		
    }

    @Override
    public void test1() {

    }
}

静态方法(java8)

​ 静态方法格式:在方法前加static 关键字

​ 注意事项:静态方法只能通过接口名称调用,不能通过实现类名或者对象名调用。

例子:

public interface InterTest {
    void test();
    void test1();
    static void  test2(){
        System.out.print("start");
    }
}

实现类 中无法重写静态方法

public class InterTestImpl1 implements InterTest {
    @Override
    public void test() {

    }

    @Override
    public void test1() {

    }

}

调用的时候只能通过接口名称进行调用

public class LambdaTest {
    public static void main(String[] args) {
            InterTest test = new InterTestImpl1();
            // 普通方法调用
            test.test();
            // 静态方法调用
            InterTest.test2();
    }
}

私有方法(java9)

在java8中有了默认方法和静态方法,如果在在一个接口中有两个默认方法或者静态方法的时候,而且两个方法中有公用的代码块,便会出现代码冗余;

例如:

public interface InterTest {
    static void  test2(){
        System.out.print("我是test2");
        System.out.print("早上起床");
        System.out.print("洗漱");
        System.out.print("吃饭");
        System.out.print("出门");
    }
    static void test3(){
        System.out.print("我是test3");
        System.out.print("早上起床");
        System.out.print("洗漱");
        System.out.print("吃饭");
        System.out.print("出门");
    }
}

如上代码出现了很多代码冗余,但是这些代码是接口的静态方法,并不需要在实现中使用,那么私有方法的出现解决了此问题;

public interface InterTest {
    default  void test1(){
        System.out.print("我是test1");
        test2();
    }
    static void  test2(){
        System.out.print("我是test2");
        test4();
    }
    static void test3(){
        System.out.print("我是test3");
        test4();
    }
    private static void test4(){
        System.out.print("早上起床");
        System.out.print("洗漱");
        System.out.print("吃饭");
        System.out.print("出门");
    }
}

接口的私有方法和平时的私有方法的声明方式是一样的。并且发现,默认方法是可以调用静态方法的,但是静态方法不能调用默认方法。

方法引用

个人感觉方法引用比较难理解。。。。

如果我们在Lambda 中想要写的代码块已经存在,那么就没有必要再重复写了,那么在这种情况下如何引用呢?

例子:

public interface ILambdaTest {
    void start(String s);
}

调用此接口

public class LambdaTest {
    public static void main(String[] args) {
        LamTest(s->{
              show(s);
          });
    }

    public static void LamTest(ILambdaTest test){
        test.start("hello");
    }

    public static void show(String s){
        System.out.println("你好"+s);
        System.out.println("我是很复杂的代码1");
        System.out.println("我是很复杂的代码2");
    }
}

如此调用是之前用Lambda的方式调用,现在我们可以方法引用

public class LambdaTest {
    public static void main(String[] args) {
        LamTest(LambdaTest::show);
    }

    public static void LamTest(ILambdaTest test){
        test.start("hello");
    }

    public static void show(String s){
        System.out.println("你好"+s);
        System.out.println("我是很复杂的代码1");
        System.out.println("我是很复杂的代码2");
    }
}

或者如下写法

public class LambdaTest {
    public static void main(String[] args) {
        LamTest(s->System.out.println(s));
        // 两行代码的结果是一样的
        LamTest(System.out::println);
    }

    public static void LamTest(ILambdaTest test){
        test.start("hello");
    }
}


此处方法引用,从s->{}LambdaTest:show 这个方法的引用意思是重写接口的实现,并且把入参传入到show(String s) 方法的s中,只不过很多操作都省略了,

​ 一般情况下, 可推导的内容就是可以省略的。

说明:

:: 该符号是引用运算符,而它所在的表达式是方法的应用

例如最后的写法中:

  • Lambda中写法

    LamTest(s->System.out.println(s));此写法是参数s传到Sysout.out.println中进行打印。

  • 方法引用写法

    LamTest(System.out::println); 方法引用的写法更加简洁

推导和省略

  • 如果使用了Lambda,那么可根据“可推导就可以省略”的原则,无需要指定参数类型,也不用指定重载形式。
  • 如果是方法引用,也可以根据上下文进行推导。
  • 方法应用是Lambda的孪生兄弟。

Lambda支持的方法引用

常见的引用方式:

  • 引用类方法
  • 引用对象的实例方法
  • 引用类的实例方法
  • 引用构造器

引用类方法

应用类的静态方法

格式: 类名::静态方法名

例如:

定义接口

public interface ILambdaTest {
    Integer start(String s);
}

public class LambdaTest {
    public static void main(String[] args) {
        //Lambda 表达式是调用
        LamTest(s->Integer.parseInt(s));
        // 方法引用进行调用
        LamTest(Integer::parseInt);
        
        // 两个方法调用的接口是一样的
    }

    public static void LamTest(ILambdaTest test){
        Integer i = test.start("123");
        System.out.println(i);
    }
}

引用对象的方法

格式: 对象::成员方法

例子:

定义接口

public interface ILambdaTest {
    Integer start(String s);
}
public class LambdaTest {
    public static void main(String[] args) {
        // Lambda 表达式调用
        LamTest(s->Integer.parseInt(s));
        // 方法引用方式调用
         LambdaTest test = new LambdaTest();
         LamTest(test::show);
    }
    private Integer  show(String s){
         return Integer.parseInt(s);
    }
    public static void LamTest(ILambdaTest test){
        Integer i = test.start("123");
        System.out.println(i);
    }
}

引用类的实例方法

例如:

public interface ILambdaTest {
    Integer start(LambdaTest s,String str);
}

如上接口,接口中的参数存在一个类的实例;

如上该如何调用? 写法如下:

public class LambdaTest {
    public static void main(String[] args) {
        // Lambda 表达式调用
        LamTest((s,y)->s.show(y));
        // 方法引用方式调用
         LamTest(LambdaTest::show);
        
        // 说明: 如果是类的实例方法调用的话,第一个参数是调用者
        // 剩下的是传递给对应方法作为参数
        // 如上说明LambdaTest:show 
        // 表示:s调用show方法,并且传递给的参数是y;
        // s 就是LamTest中的new LambdaTest()
        // y 就是“123”
    }
    private Integer  show(String s){
         return Integer.parseInt(s);
    }
    public static void LamTest(ILambdaTest test){
        Integer i = test.start(new LambdaTest(),"123");
        System.out.println(i);
    }
}

引用构造器

Lambda表达式被构造器替代的时候,它的所有形参全部会传递给构造器作为参数

例子:

public class UserInfo {
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public UserInfo(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}

创建接口

public interface ILambdaTest {
    UserInfo start(Long id,String name);
}

public class LambdaTest {
    public static void main(String[] args) {
        // Lambda 表达式调用
        LamTest((s,y)->new UserInfo(s,y));
        // 方法引用方式调用
         LamTest(UserInfo::new);
        //Lambda表达式被构造器替代的时候,它的所有形参全部会传递给构造器作为参数
    }
    private Integer  show(String s){
         return Integer.parseInt(s);
    }
    public static void LamTest(ILambdaTest test){
        UserInfo userInfo = test.start(1L,"123");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_30285985/article/details/100064183
今日推荐