gpt4 book ai didi

java - 枚举感知的 ServiceLoader 实现?

转载 作者:行者123 更新时间:2023-11-30 01:55:19 34 4
gpt4 key购买 nike

我希望能够将枚举类型指示为接口(interface)实现,然后通过 ServiceLoader API 将所有枚举加载为接口(interface)的单独实例/实现。此用例的一个示例是允许 API 的下游用户指定自定义值,但提供具有标准/通用实现的枚举。我的接口(interface)只需要一个 String name(),因此任何枚举都已经实现了它。

例如,Java NIO API 中的 CopyOption 接口(interface),以及提供的 StandardCopyOption 枚举。假设我想通过 ServiceLoader 将所有 CopyOption(甚至是类路径上的新选项以及标准)加载到单个迭代器(或者我愿意接受其他建议! )

我最终通过批量复制 ServiceLoader 并修改它以在实例化失败时尝试使用 getEnumConstants 使其工作(try 中的部分)这是它当前的工作方式,catch 中的部分是我添加/更改的部分):

try {
S p = service.cast(c.newInstance());
providers.put(cn, p);
return p;
} catch (Throwable x) {
Object[] arr = c.getEnumConstants();
if (arr == null || arr.length == 0) {
fail(service, "Provider " + cn + " could not be instantiated", x);
}

List<S> list = new LinkedList<>();
for (Object o : arr) {
Enum<?> e = (Enum<?>) o;
S p = service.cast(e);
providers.put(cn + e.ordinal(), p);
list.add(p);
}
subiter = list.iterator();
return subiter.next();
}

我还添加了一些代码,如果 subiter 存在并且有 next,则在转到下一个类名之前对其进行迭代。

我的问题是:有更好的方法吗?

如果最终用途不清楚,现在可以通过上述修改实现:

interface ImageType {
String name();
}

@AutoService(ImageType.class)
enum StandardImageType implements ImageType {
IMAGE,
VECTOR,
RASTER,
HANDWRITING,
ICON,
LOGO,
SEAL,
RULE,
BARCODE
}

最佳答案

随着 Java 模块的引入,an alternative通过默认构造函数实例化已添加到服务提供者中。但它仅在提供程序位于命名模块中时才有效。

提供者类可以声明 public static T provider()方法其中 T是服务类型。然后,提供者实现类甚至不需要实现或扩展T本身。

既不是数组,也不是像 List<ImageType> 这样的泛型类型可以用作服务类型,我们需要另一种类型来潜在地封装多个实际实例,例如

package somemodule;

import java.util.function.Supplier;

public interface ImageType {
String name();
interface ImageTypes extends Supplier<ImageType[]> {}
}

package somemodule;

public enum StandardImageType implements ImageType {
IMAGE,
VECTOR,
RASTER,
HANDWRITING,
ICON,
LOGO,
SEAL,
RULE,
BARCODE;

public static ImageTypes provider() {
return StandardImageType::values;
}
}

和一个模块声明,例如

module SomeModule {
uses somemodule.ImageType.ImageTypes;
provides somemodule.ImageType.ImageTypes with somemodule.StandardImageType;
}

允许写入,例如

List<ImageType> all = ServiceLoader.load(ImageType.ImageTypes.class)
.stream().flatMap(p -> Arrays.stream(p.get().get()))
.collect(Collectors.toList());

模块内的某个位置(或具有 uses somemodule.ImageType.ImageTypes; 声明的任何其他模块)。

关于java - 枚举感知的 ServiceLoader 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54719780/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com