一、实验性功能说明
@ExtensionMethod
是在lombok v0.11.2
中作为实验性功能引入的。
原因:
- 对代码风格的影响很大。
- 想用实用程序方法来扩展公共类,但到目前为止,
lombok
还没有一个适合这种运行时依赖关系的好的分发方法。 - 对
eclipse
的影响相当大,自动完成e.d.
在netbeans
中还不能工作。 - @ExtensionMethod在方法上是否合法?它应该在包上合法吗?
- 这个功能有更多与之相关的错误,而这是一个很大的维护负担。
当前状态:保持 - 目前我们觉得这个功能不会很快脱离实验状态,但它不会有明显的变化,对它的支持也不可能在未来的lombok
版本中被删除。
二、简介
你可以制作一个包含一堆public
, static
方法的类,这些方法都至少有一个参数。这些方法将扩展第一个参数的类型,就像它们是实例方法一样,使用@ExtensionMethod
特性。
例如,如果你创建了 public static String toTitleCase(String in) { ... }
,你可以使用@ExtensionMethod
特性,让它看起来像java.lang.String
类有一个名为toTitleCase
的方法,它没有参数。静态方法的第一个参数填补了实例方法中this
的这个角色。
所有public
、static
、至少有一个类型不是原始的参数的方法都被认为是扩展方法,每个方法都将被注入第一个参数的类型的名字空间,就像它们是实例方法一样。就像上面的例子,一个看起来像: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!
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。