Java函数式编程

科长
2023-07-10 / 0 评论 / 111 阅读 / 正在检测是否收录...
在程序开发中使用函数式编程,可以减少冗杂的代码,加快开发速度等。接下来,我将给大家讲讲在 Java 8 中的三种函数式编程的方法,lambda 表达式、:: 符号和 Optional 类,下面是详细内容。

1、函数式编程

函数式编程(Functional Programming)属于编程范式(Programming Paradigm)中的用语,此外还有命令式编程(Imperative Programing)等,有兴趣的同学可以自行了解,我们这里大概解释一下函数式编程,在函数式编程中,输入一旦确定了,输出都确定了,函数调用的结果只依赖于传入的输入变量和内部逻辑,不依赖于外部,这样的写出的函数没有副作用。举个例子:

public class Test {
    private int a = 1;

    public int add(int b) {
        return a + b;
    }

    public int pow(int c) {
        return c * c;
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.add(1);
        t.pow(2);
    }
}

上面代码中add(int b)这个方法就不符合函数式编程,这个函数调用后的结果不确定,它的结果不仅取决于b还取决于字段a。而pow(int c)这函数就是符合函数式编程的典范,只要调用它,输入的值c确定了返回值就肯定确定了。
在函数式编程中,函数也是一等公民,可以被当做参数传递,可以被赋值,被引用,可以把它当做一种数据类型来对待,如果你会使用javascript之类的语言就可以有更深的体会。如果要深入了解这种编程范式可以自行网上搜素资料了解。

2、lambda表达式

lambda表达式是jdk8中的新特性,上面讲函数式编程就是引入这个,oracle在jdk8中引入了lambda,从此Java中开始对函数式编程的部分支持。
Java中lambda表达式的语法结构:(params) -> expression由三部分构成,第一部分是括号以及括号内部的形式参数,第二部分是->箭头符号,第三部分是expression方法体,方法体可以是代码块也可以是执行表达式。

// lambda 表达式 完整状态 有入参 有返回 有代码块
(int a, int b) -> {
   int c = a + b;
  return c;
}
// 当代码不需要返回值 则可省去 return
(int a, int b) -> {
  int c = a + b;
}
// 当代码只有一句话的时候可以省去 大括号
(int a, int b) -> a + b;
// 同样可以省略形参类型
(a, b) -> a + b;
// 当只有一个参数时, 可以省去形参的小括号
 a -> a * a;

接下来使用lambda表达式来定义和实现一个函数式接口:

@FunctionalInterface
public interface ITest {
    int add(int a, int b);
}

内部匿名类实现方式:

public static void main(String[] args) {
  ITest iTest = new ITest() {
  @Override
  public int add(int a, int b) {
      return a + b;
    }
  };
  iTest.add(1, 1);
}

Lambda实现方式:

 public static void main(String[] args) {
   ITest t = (a, b) -> a + b;
   t.add(1, 1);
 }

使用lambda表达式会使代码更加的优雅

3、使用双冒号::符号

对上面的Lambda实现方式进行进步一步的优化:

public static void main(String[] args) {
  ITest t = Integer::sum;
  t.add(1, 1);
}

双冒号的使用方式:类名::静态方法名或者 类的实例::实例方法

4、Optional类

Optional也是jdk8中的一个新的类的,它给予我们更加优雅的方式来处理Java语言中的NPE异常。可以从一定程度上代替if判断, 介绍相关接口:

  • empty 创建一个空的Optional对象
  • of 和ofNullable

of创建一个Optional对象, 如果传入的参数为空则跑出NPE异常.
ofNullable和上面一样, 但是当传入参数为空的时候会调用empty方法创建一个空Optional对象.

Optional<String> of = Optional.of("waxxd");
// 传入空参数会抛出NullPointerException异常
Optional<String> ofNull = Optional.of(null); 
// 以下两句都正常执行
Optional<String> ofNullable = Optional.ofNullable("waxxd");
// 参数为空的时候相当调用Optional.empty()
Optional<String> ofNullableNull = Optional.ofNullable(null); 

get/orElse/orElseGet/orElseThrow

// get 获取Option包裹的值如果值为null则抛出NoSuchElementException异常
String aa = Optional.of("aa").get();
// orElse 获取值如果值为空则返回orElse设置的默认值
String aa1 = Optional.of("aa").orElse("bb");
// orElseGet 获取值如果值为空则内部可以是一个实现Supplier接口的匿名内部类调用提供返回结果
String aa2 = Optional.of("aa").orElseGet( () -> "aaa".toUpperCase());
// orElseThrow获取值如果不存在则抛出后面的异常
Optional.empty().orElseThrow(IllegalArgumentException::new);

// 实际的应用, 也就是上文所说的如何优化if
// 比如你有个接口, 用户传入参数Integer type, 用户也可以选择不传, 不传我们为它设置默认值1
public void f(Integer type){
    if(type = null) {
        type = 1;
    }
    Optional.ofNullable(type).orElse(1);
}
0

评论 (0)

取消