Я хотел бы иметь возможность указать тип перечисления как реализацию интерфейса, а затем загрузить все перечисления как отдельные экземпляры / реализации интерфейса через API ServiceLoader
.Пример этого варианта использования мог бы позволить нижестоящим пользователям моего API указывать пользовательские значения, но предоставлять перечисление со стандартными / общими реализациями.Мой интерфейс требует только String name()
, поэтому любое перечисление уже реализует его.
Например, интерфейс CopyOption
в API Java NIO с предоставленным перечислением StandardCopyOption
.Скажем, я хотел загрузить все CopyOption
s, даже новые на пути к классам вместе со стандартами, в один итератор через ServiceLoader
(или я открыт для других предложений!)
Я наконец-то получилчтобы он работал, скопировав 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
существует и имеет следующий, он повторяется перед переходом к следующему имени класса.
Мой вопрос:Есть ли лучший способ?
В случае, если конечное использование не ясно, теперь это возможно с вышеуказанными модификациями:
interface ImageType {
String name();
}
@AutoService(ImageType.class)
enum StandardImageType implements ImageType {
IMAGE,
VECTOR,
RASTER,
HANDWRITING,
ICON,
LOGO,
SEAL,
RULE,
BARCODE
}