Lombok 表达式

本文介绍了Lombok表达式和Java 8的Lambda表达式,包括命令式与函数式编程的区别,函数式接口的概念,以及Lambda的匿名、简洁特性。详细讲解了函数描述符、类型推断、方法引用等关键概念,并列举了Java 8中常见的函数式接口。文章总结了Lambda表达式的重要性和使用场景,强调其在函数式编程中的作用。

https://github.com/biezhi/learn-java8/tree/master/java8-lambda

Lombok表达式源码: git clone git@github.com:biezhi/learn-java8.git

ambda 表达式

命令式和函数式

命令式编程:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。 声明式编程:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。

什么是函数式编程?

每个人对函数式编程的理解不尽相同。 我的理解是:在完成一个编程任务时,通过使用不可变的值或函数,对他们进行处理,然后得到另一个值的过程。 不同的语言社区往往对各自语言中的特性孤芳自赏。现在谈 Java 程序员如何定义函数式编程还为时尚早,但是,这根本不重要! 我们关心的是如何写出好代码,而不是符合函数式编程风格的代码。

行为参数化

把算法的策略(行为)作为一个参数传递给函数。

lambda 管中窥豹

  • 匿名:它不像普通的方法那样有一个明确的名称:写得少而想得多!
  • 函数:Lambda函数不像方法那样属于某个特定的类。但和方法一样,Lambda有参数列表、函数主体、返回类型,还可能有可以抛出的异常列表。
  • 传递:Lambda表达式可以作为参数传递给方法或存储在变量中。
  • 简洁:无需像匿名类那样写很多模板代码。

函数描述符

函数式接口的抽象方法的签名基本上就是Lambda表达式的签名,这种抽象方法叫作函数描述符。

函数式接口,类型推断

函数式接口定义且只定义了一个抽象方法,因为抽象方法的签名可以描述Lambda表达式的签名。 函数式接口的抽象方法的签名称为函数描述符。 所以为了应用不同的Lambda表达式,你需要一套能够描述常见函数描述符的函数式接口。

Java 8中的常用函数式接口

函数式接口函数描述符原始类型特化
Predicate<T>T->booleanIntPredicate,LongPredicate, DoublePredicate
Consumer<T>T->voidIntConsumer,LongConsumer, DoubleConsumer
Function<T,R>T->RIntFunction<R>, IntToDoubleFunction,
IntToLongFunction, LongFunction<R>,
LongToDoubleFunction, LongToIntFunction,
DoubleFunction<R>, ToIntFunction<T>,
ToDoubleFunction<T>, ToLongFunction<T>
Supplier<T>()->TBooleanSupplier,IntSupplier, LongSupplier, DoubleSupplier
UnaryOperator<T>T->TIntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
BinaryOperator<T>(T,T)->TIntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
BiPredicate<L,R>(L,R)->boolean 
BiConsumer<T,U>(T,U)->voidObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T>
BiFunction<T,U,R>(T,U)->RToIntBiFunction<T,U>, ToLongBiFunction<T,U>, ToDoubleBiFunction<T,U>

Lambdas及函数式接口的例子

使用案例Lambda 的例子对应的函数式接口
布尔表达式(List<String> list) -> list.isEmpty()Predicate<List<String>>
创建对象() -> new Project()Supplier<Project>
消费一个对象(Project p) -> System.out.println(p.getStars())Consumer<Project>
从一个对象中选择/提取(int a, int b) -> a * bIntBinaryOperator
比较两个对象(Project p1, Project p2) -> p1.getStars().compareTo(p2.getStars())Comparator<Project> 或 BiFunction<Project,
Project, Integer> 或 ToIntBiFunction<Project, Project>

方法引用

方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递它们。

本节课小结

  • lambda 表达式可以理解为一种匿名函数:它没有名称,但有参数列表、函数主体、返回 类型,可能还有一个可以抛出的异常的列表。
  • lambda 表达式让你可以简洁地传递代码。
  • 函数式接口就是仅仅声明了一个抽象方法的接口。
  • 只有在接受函数式接口的地方才可以使用 lambda 表达式。
  • lambda 表达式允许你直接内联,为函数式接口的抽象方法提供实现,并且将整个表达式作为函数式接口的一个实例。
  • Java 8自带一些常用的函数式接口,放在 java.util.function 包里,包括 Predicate<T>Function<T,R>Supplier<T>Consumer<T> 和 BinaryOperator<T>
  • Lambda表达式所需要代表的类型称为目标类型。
  • 方法引用让你重复使用现有的方法实现并直接传递它们。
  • Comparator``、PredicateFunction` 等函数式接口都有几个可以用来结合 lambda 表达式的默认方法。

 

@UtilityClass 标签默认将方法 变成static类型

 lombok.experimental.UtilityClass

例如:

/**
 * 路由缓存工具类
 */
@UtilityClass
public class RouteCacheHolder {

   private Cache<String, RouteDefinitionVo> cache = CacheUtil.newLFUCache(100);

   /**
    * 获取缓存的全部对象
    * @return routeList
    */
   public List<RouteDefinitionVo> getRouteList() {
      List<RouteDefinitionVo> routeList = new ArrayList<>();
      cache.forEach(route -> routeList.add(route));
      return routeList;
   }

   /**
    * 更新缓存
    * @param routeList 缓存列表
    */
   public void setRouteList(List<RouteDefinitionVo> routeList) {
      routeList.forEach(route -> cache.put(route.getId(), route));
   }

   /**
    * 清空缓存
    */
   public void removeRouteList() {
      cache.clear();
   }
}

 

### Lombok 表达式用法示例解释 #### 使用 `@Getter` 和 `@Setter` 通过使用 Lombok 的 `@Getter` 和 `@Setter` 注解,可以在类中自动生成 getter 和 setter 方法。这减少了样板代码的数量并提高了开发效率。 ```java import lombok.Getter; import lombok.Setter; @Getter @Setter public class User { private String name; private int age; } ``` 上述代码会自动为 `name` 和 `age` 字段生成相应的 getter 和 setter 方法[^3]。 #### 使用 `@ToString`, `@EqualsAndHashCode` 这些注解用于简化对象的字符串表示形式以及相等性和哈希码逻辑。它们同样能够显著减少重复性的模板代码。 ```java import lombok.ToString; import lombok.EqualsAndHashCode; @ToString(callSuper = true) @EqualsAndHashCode(of = {"id"}) class Employee extends Person { private long id; private double salary; } ``` 这里,`Employee` 类将会拥有基于其父类属性加上自己特有属性(即 `id`)来计算 hashCode 和 equals 方法的能力,并且可以通过调用 toString 显示所有字段的信息[^5]。 #### 构造器简化 - `@NoArgsConstructor`, `@AllArgsConstructor`, `@RequiredArgsConstructor` Lombok 提供了几种不同的构造函数生成方式: - `@NoArgsConstructor`: 创建无参构造器; - `@AllArgsConstructor`: 创建全参构造器; - `@RequiredArgsConstructor`: 对于 final 或带有约束条件(@NonNull) 的成员变量创建相应参数的构造器。 ```java @NoArgsConstructor @AllArgsConstructor static class Address { private String streetName; private int houseNumber; } // Only generates constructor with parameters for non-null fields. @RequiredArgsConstructor(staticName = "of") static class Product { private final String productName; private Double price; // Optional field without a parameter in the generated constructor. } ``` 这段代码展示了如何利用 Lombok 自动生成不同类型的构造器,从而避免手动编写冗长而简单的初始化代码[^4]。 #### 数据类简化 - `@Data` 当希望一次性获得多个功能时,可以考虑使用 `@Data` 注解。它相当于组合了 `@Getter`, `@Setter`, `@ToString`, `@EqualsAndHashCode` 以及默认的 noargs-constructor (`@NoArgsConstructor`) 功能于一体。 ```java @Data public static class Book { private String title; private Author author; private List<String> chapters; } ``` 此例子中的 `Book` 类不仅拥有了所有的访问器方法,还具备良好的打印输出能力和合理的比较行为。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值