Я думаю, что наиболее важным аспектом этого кода является Function
в отличие от самого метода. Я также не думаю, что имеет смысл переключать подклассы, которые вы разрешаете в теле Function
, так как вы уже знаете, какой тип Number
вы хотите вернуть во время создания Function
. Также немного проблематично, что ваш метод дает сбой, если, скажем, BigInteger.class
.
Учитывая это, я хотел бы создать вспомогательный класс (назовем его Numbers
) и предоставить для него методы, каждый из которых возвращает Function
(который может быть enum
singleton) для анализа String
как определенный тип Number
. То есть:
public class Numbers {
public static Function<String, Integer> parseIntegerFunction() { ... }
public static Function<String, Long> parseLongFunction() { ... }
...
}
Каждый из них может быть реализован примерно так:
public static Function<String, Integer> parseIntegerFunction() {
return ParseIntegerFunction.INSTANCE;
}
private enum ParseIntegerFunction implements Function<String, Integer> {
INSTANCE;
public Integer apply(String input) {
return Integer.valueOf(input);
}
@Override public String toString() {
return "ParseIntegerFunction";
}
}
Это может быть использовано, однако пользователи хотят:
List<String> strings = ...
List<Integer> integers = Lists.transform(strings, Numbers.parseIntegerFunction());
Этот подход имеет несколько преимуществ перед вашим:
- Не требует никакого переключения в
Function
... мы знаем, какой тип номера мы создаем, и просто делаем это. Быстрее.
- является более гибким в том смысле, что каждый
Function
может использоваться везде, где ... пользователи не обязаны использовать его так, как это делает ваш метод (копирование преобразованных значений в ImmutableList
.
- Вы создаете только
Function
, которые вы действительно хотите разрешить. Если функции синтаксического анализа BigInteger
нет, пользователи просто не смогут ее вызвать, в отличие от того, чтобы было вполне законно делать это во время компиляции, а затем отказывать во время выполнения, как в вашем примере.
В качестве примечания я бы рекомендовал сделать тип возврата любого метода, который возвращает ImmutableList
, будет ImmutableList
вместо List
... он предоставляет информацию, полезную для клиентов метода.
Edit:
Если вам действительно нужно что-то более динамичное (т.е. вы хотите, чтобы классы с экземпляром некоторого Class<T extends Number>
могли преобразовать String
s в этот Number
тип), вы также можете добавить метод поиска вроде:
public static <T extends Number> Function<String, T> parseFunctionFor(Class<T> type) {
// lookup the function for the type in an ImmutableMap and return it
}
Это имеет те же проблемы, что и ваш оригинальный метод, хотя, если есть подкласс Number
, для которого вы не предоставляете Function
. Также не похоже, что было бы много ситуаций, когда это было бы полезно.