
什么是扩展方法
为什么需要扩展方法
// "123,456,123,789"String str = redisService.get(someKey)
String itemIdStrs = String.join(",", new LinkedHashSet<>(Arrays.asList(str.split(","))));
String itemIdStrs = Arrays.stream(str.split(",")).distinct().collect(Collectors.joining(","));
String itemIdStrs = str.split(",").toList().toSet().join(",");
可以对现有的类库,进行直接增强,而不是使用工具类
相比使用工具类,使用类型本身的方法写代码更流畅更舒适
代码更容易阅读,因为是链式调用,而不是用静态方法套娃
在 Java 中怎么实现扩展方法

好吧,ChatGPT 认为 Java 里面的扩展方法就是通过工具类提供的静态方法 :)。所以接下来我将介绍一种全新的黑科技:
Manifold(https://github.com/manifold-systems/manifold)
准备条件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">...<properties><manifold.version>2022.1.35</manifold.version></properties><dependencies><dependency><groupId>systems.manifold</groupId><artifactId>manifold-ext</artifactId><version>${manifold.version}</version></dependency>...</dependencies><!--Add the -Xplugin:Manifold argument for the javac compiler--><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>8</source><target>8</target><encoding>UTF-8</encoding><compilerArgs><arg>-Xplugin:Manifold no-bootstrap</arg></compilerArgs><annotationProcessorPaths><path><groupId>systems.manifold</groupId><artifactId>manifold-ext</artifactId><version>${manifold.version}</version></path></annotationProcessorPaths></configuration></plugin></plugins></build></project>
<annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></path><path><groupId>systems.manifold</groupId><artifactId>manifold-ext</artifactId><version>${manifold.version}</version></path></annotationProcessorPaths>
编写扩展方法
package com.alibaba.zhiye.extensions.java.lang.String;import manifold.ext.rt.api.Extension;import manifold.ext.rt.api.This;import org.apache.commons.lang3.StringUtils;/*** String 的扩展方法*/@Extensionpublic final class StringExt {public static String[] split(@This String str, char separator) {return StringUtils.split(str, separator);}}
可以发现本质上还是工具类的静态方法,但是有一些要求:
工具类需要使用 Manifold 的 @Extension 注解
静态方法中,目标类型的参数,需要使用 @This 注解
工具类所在的包名,需要以 extensions.目标类型全限定类名 结尾
—— 用过 C# 的同学应该会会心一笑,这就是模仿的 C# 的扩展方法。


[Ljava.lang.String;@511d50c0 什么的,Goodbye,再也不见~
package com.alibaba.zhiye.extensions.java.util.Collection;import manifold.ext.rt.api.Extension;import manifold.ext.rt.api.This;import java.util.Collection;/*** Collection 的扩展方法*/@Extensionpublic final class CollectionExt {public static boolean isNullOrEmpty(@This Collection<?> coll) {return coll == null || coll.isEmpty();}}
List<String> list = getSomeNullableList();// list 如果为 null 会进入 if 块,而不会触发空指针异常if (list.isNullOrEmpty()) {// TODO}
数组扩展方法




package com.alibaba.zhiye.extensions.java.lang.Object;import manifold.ext.rt.api.Extension;import manifold.ext.rt.api.Self;import manifold.ext.rt.api.This;import java.util.Optional;/*** Object 的扩展方法*/@Extensionpublic final class ObjectExt {public static Optional<@Self Object> asOpt(@This Object obj) {return Optional.ofNullable(obj);}}
Optional.ofNullable(someObj).filter(someFilter).map(someMapper).orElseGet(someSupplier);
someObj.asOpt().filter(someFilter).map(someMapper).orElseGet(someSupplier);
扩展静态方法
List<String> list = List.of("a", "b", "c");Set<String> set = Set.of("a", "b", "c");Map<String, Integer> map = Map.of("a", 1, "b", 2, "c", 3);
package com.alibaba.aladdin.app.extensions.java.util.List;import manifold.ext.rt.api.Extension;import manifold.ext.rt.api.This;import java.util.Arrays;import java.util.Collections;import java.util.List;/*** List 扩展方法*/@Extensionpublic final class ListExt {/*** 返回只包含一个元素的不可变 List*/@Extensionpublic static <E> List<E> of(E element) {return Collections.singletonList(element);}/*** 返回包含多个元素的不可变 List*/@Extension@SafeVarargspublic static <E> List<E> of(E... elements) {return Collections.unmodifiableList(Arrays.asList(elements));}}
建议
关于 Manifold
谨慎添加扩展方法
public static boolean isValidParam(String str) {return StringUtils.isNotBlank(str) && !"null".equalsIgnoreCase(str);}
文章转载自阿里开发者,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




