Я пишу сериализуемый класс, который принимает несколько аргументов, включая Function
:
public class Cls implements Serializable {
private final Collection<String> _coll;
private final Function<String, ?> _func;
public Cls(Collection<String> coll, Function<String, ?> func) {
_coll = coll;
_func = func;
}
}
func
хранится в переменной-члене и поэтому нуждается в сериализации. Java lambdas являются сериализуемыми, если тип, которому они назначены, сериализуется. Какой лучший способ обеспечить, чтобы Function
, который я получил в моем конструкторе, сериализуем, если он создан с помощью лямбда?
-
Создайте тип
SerializableFunction
и используйте это:public interface SerializableFunction<F, R> implements Function<F, R>, Serializable {} .... public Cls(Collection<String> coll, SerializableFunction<String, ?> func) {...}
Вопросы:
- В настоящее время существует несоответствие между аргументами
coll
иfunc
, в том, чтоfunc
объявляется сериализуемым в сигнатуре, ноcoll
нет, но оба они должны быть сериализуемыми для работы. - Это не разрешает сериализацию других реализаций
Function
.
- В настоящее время существует несоответствие между аргументами
-
Используйте параметр типа в конструкторе:
public <F extends Function<String, ?> & Serializable> Cls(Collection<String> coll, F func) {...}
Вопросы:
- Более гибкий, чем 1, но более запутанный.
- До сих пор существует несоответствие между двумя аргументами - требуется аргумент
func
для реализацииSerializable
в иерархии типа времени компиляции, ноcoll
просто требуется как-то сериализуться (хотя это требование может быть выполнено если необходимо).
EDIT Этот код на самом деле не компилируется при попытке вызова с помощью ссылки лямбда или метода.
-
Оставьте его для вызывающего
Это требует, чтобы вызывающий пользователь знал (из javadocs или проб и ошибок), что аргумент должен быть сериализуемым, и приведение в соответствие:
Cls c = new Cls(strList, (Function<String, ?> & Serializable)s -> ...);
или
Cls c = new Cls(strList, (Function<String, ?> & Serializable)Foo::processStr);
Это уродливая ИМО, и первоначальная наивная реализация использования лямбда гарантированно сломается, а не работает как с
coll
(поскольку большинство коллекций как-то сериализуется). Это также подталкивает деталь реализации класса к вызывающему.
В настоящий момент я склоняюсь к варианту 2, как тот, который налагает наименьшую нагрузку на вызывающего, но я не думаю, что здесь идеальное решение. Любые другие предложения относительно того, как это сделать должным образом?
EDIT. Возможно, необходим какой-то фон. Это класс, который запускается внутри storm в болте, который сериализуется для переноса на удаленный кластер для его выполнения. Функция выполняет операцию над обработанными кортежами при запуске в кластере. Таким образом, это очень большая часть цели класса, что она сериализуема и что аргумент функции сериализуем. Если это не так, то класс неприменим.