Lombok 使用教程-@ExtensionMethod | 向现有类型中添加方法

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

一、实验性功能说明

@ExtensionMethod是在lombok v0.11.2中作为实验性功能引入的。

原因:

  • 对代码风格的影响很大。
  • 想用实用程序方法来扩展公共类,但到目前为止,lombok还没有一个适合这种运行时依赖关系的好的分发方法。
  • eclipse的影响相当大,自动完成e.d.netbeans中还不能工作。
  • @ExtensionMethod在方法上是否合法?它应该在包上合法吗?
  • 这个功能有更多与之相关的错误,而这是一个很大的维护负担。

当前状态:保持 - 目前我们觉得这个功能不会很快脱离实验状态,但它不会有明显的变化,对它的支持也不可能在未来的lombok版本中被删除。

二、简介

你可以制作一个包含一堆publicstatic方法的类,这些方法都至少有一个参数。这些方法将扩展第一个参数的类型,就像它们是实例方法一样,使用@ExtensionMethod特性。

例如,如果你创建了 public static String toTitleCase(String in) { ... },你可以使用@ExtensionMethod特性,让它看起来像java.lang.String类有一个名为toTitleCase的方法,它没有参数。静态方法的第一个参数填补了实例方法中this的这个角色。

所有publicstatic、至少有一个类型不是原始的参数的方法都被认为是扩展方法,每个方法都将被注入第一个参数的类型的名字空间,就像它们是实例方法一样。就像上面的例子,一个看起来像:foo.toTitleCase()的调用被替换为ClassContainingYourExtensionMethod.toTitleCase(foo);。注意,如果foo是空的,实际上并不是一个即时的NullPointerException —— 它像其他参数一样被传递。

你可以向@ExtensionMethod注解传递任意数量的类;它们都将被搜索到扩展方法。这些扩展方法适用于被注解的类中的任何代码。

Lombok(目前)没有任何运行时依赖,这意味着lombok(目前)没有提供任何有用的扩展方法,所以你必须自己制作。然而,这里有一个可能会激发你的想象力。

    public class ObjectExtensions {
    	public static <T> T or(T object, T ifNull) {
    		return object != null ? object : ifNull;
    	}
    }

有了上面的类,如果你在类定义中加入@ExtensionMethod(ObjectExtensions.class),你就可以写。

    String x = null;
    System.out.println(x.or("Hello, World!"));

上面的代码不会因为NullPointerException而失败;它实际上会输出Hello, World!

三、示例比较

1. Lombok 写法

    import lombok.experimental.ExtensionMethod;
    
    @ExtensionMethod({java.util.Arrays.class, Extensions.class})
    public class ExtensionMethodExample {
      public String test() {
        int[] intArray = {5, 3, 8, 2};
        intArray.sort();
        
        String iAmNull = null;
        return iAmNull.or("hELlO, WORlD!".toTitleCase());
      }
    }
    
    class Extensions {
      public static <T> T or(T obj, T ifNull) {
        return obj != null ? obj : ifNull;
      }
      
      public static String toTitleCase(String in) {
        if (in.isEmpty()) return in;
        return "" + Character.toTitleCase(in.charAt(0)) +
            in.substring(1).toLowerCase();
      }
    }

2. Java 标准写法

    public class ExtensionMethodExample {
      public String test() {
        int[] intArray = {5, 3, 8, 2};
        java.util.Arrays.sort(intArray);
        
        String iAmNull = null;
        return Extensions.or(iAmNull, Extensions.toTitleCase("hELlO, WORlD!"));
      }
    }
    
    class Extensions {
      public static <T> T or(T obj, T ifNull) {
        return obj != null ? obj : ifNull;
      }
      
      public static String toTitleCase(String in) {
        if (in.isEmpty()) return in;
        return "" + Character.toTitleCase(in.charAt(0)) +
            in.substring(1).toLowerCase();
      }
    }

四、支持的配置项

lombok.extensionMethod.flagUsage = [warning | error] (默认: not set)
Lombok@ExtensionMethod的任何使用标记为警告或错误(如果已配置)。

五、附属说明

调用被重写为对扩展方法的调用;静态方法本身没有被内联。因此,扩展方法必须在编译时和运行时都存在。

泛型完全应用于找出扩展方法。即如果您的扩展方法的第一个参数是 List<? extends String>,那么任何与之兼容的表达式都会有你的扩展方法,但其他类型的List不会。所以, List<Object> 不会得到它,但 List<String> 会。

参考文献

【1】@ExtensionMethod | Annoying API? Fix it yourself: Add new methods to existing types!

  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值