首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Enum感知的ServiceLoader实现?

Enum感知的ServiceLoader实现?
EN

Stack Overflow用户
提问于 2019-02-16 04:00:41
回答 1查看 442关注 0票数 2

我希望能够将枚举类型指定为接口实现,然后通过ServiceLoader API加载所有枚举作为接口的单独实例/实现。这个用例的一个例子是允许我的API的下游用户指定自定义值,但是提供一个带有标准/公共实现的枚举。我的接口只需要一个字符串name(),所以任何枚举都已经实现了。

例如,Java中的CopyOption接口具有提供的StandardCopyOption枚举。假设我想通过CopyOption将所有的ServiceLoader加载到一个迭代器中,即使是在类路径上的新的,也可以通过ServiceLoader加载到一个迭代器(或者我可以接受其他建议!)

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

代码语言:javascript
复制
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,则在转到下一个类名之前对其进行迭代。

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

如果最终用途还不清楚,那么通过上述修改,现在就可以这样做了:

代码语言:javascript
复制
interface ImageType {
    String name();
}

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-06 18:59:19

随着Java模块的引入,通过默认构造函数实例化的另一种已经添加到服务提供者中。但是,只有当提供程序位于指定的模块中时,它才能工作。

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

由于数组或像List<ImageType>这样的泛型类型都不能用作服务类型,因此我们需要另一种类型来封装多个实际实例。

代码语言:javascript
复制
package somemodule;

import java.util.function.Supplier;

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

代码语言:javascript
复制
package somemodule;

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

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

和一个模块声明,如

代码语言:javascript
复制
module SomeModule {
    uses somemodule.ImageType.ImageTypes;
    provides somemodule.ImageType.ImageTypes with somemodule.StandardImageType;
}

这允许写,例如。

代码语言:javascript
复制
List<ImageType> all = ServiceLoader.load(ImageType.ImageTypes.class)
        .stream().flatMap(p -> Arrays.stream(p.get().get()))
        .collect(Collectors.toList());

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54719780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档