能否将ITransform的lambda实现提升为Transform实例方法以支持Pipeline序列化
问题背景
现有自定义转换接口与Pipeline实现,需要支持序列化跨环境复用,但直接序列化lambda实现的ITransform实例存在风险,需要将lambda转换为可安全序列化的Transform子类实现。
现有代码
函数式接口定义
@FunctionalInterface public interface ITransform<I, O> extends Serializable { O process(I input); static <I, O> ITransform<I, O> of(ITransform<I, O> source) { return source; } }
抽象实现类
public abstract class Transform implements ITransform<IOvariable, IOvariable> { protected final Class<?> inputClass; public Transform(Class<?> inputClass) { this.inputClass = inputClass; } public Class<?> getInputClass() { return inputClass; } }
具体实现示例
public class ConcreteTransform extends Transform { public ConcreteTransform() { super(SampleObject.class); } @Override public IOvariable process(IOvariable input) { Class<?> inputClass = input.getClazz(); if (inputClass == this.inputClass) { return IOvariable.create(((SampleObject) input.getVariable()).getNumber()); } throw new IllegalArgumentException( "Input is " + input.getClazz() + " but this transform requires " + this.getInputClass()); } }
Pipeline使用示例
ITransform<IOvariable, IOvariable> transform = new ConcreteTransform(); ITransform<String, Integer> parseInt = ITransform.of(Integer::parseInt); ITransform<Integer, Integer> timesTwo = ITransform.of(input -> input * 2); ITransform<Integer, String> toString = ITransform.of(Object::toString); ITransform<String, String> output = ITransform.of(input -> "The output is: " + input); Pipeline pipe = new Pipeline(new SampleObject("10")) .addTransform(transform) .addTransform(parseInt) .addTransform(timesTwo) .addTransform(toString) .addTransform(prettyOutput); // 输出结果:"The output is: 20"
解决方案
以下三种方案均可实现需求,优先推荐前两种:
- 方案1:通用Lambda包装类
实现通用的Transform子类,将lambda作为构造参数传入,统一做类型校验和IOvariable的适配,代码如下:
替换原有lambda创建逻辑:public class LambdaTransform extends Transform { private final ITransform<Object, Object> logic; public <I, O> LambdaTransform(Class<I> inputClazz, ITransform<I, O> logic) { super(inputClazz); this.logic = (ITransform<Object, Object>) logic; } @Override public IOvariable process(IOvariable input) { if (!inputClass.isInstance(input.getVariable())) { throw new IllegalArgumentException( "Input type: " + input.getClazz() + ", required type: " + inputClass); } Object result = logic.process(input.getVariable()); return IOvariable.create(result); } }
注意:仅传入无外部变量捕获的lambda作为参数,即可保证LambdaTransform实例可安全序列化。Transform parseInt = new LambdaTransform(String.class, Integer::parseInt); Transform timesTwo = new LambdaTransform(Integer.class, input -> input * 2); Transform toString = new LambdaTransform(Integer.class, Object::toString); Transform output = new LambdaTransform(String.class, input -> "The output is: " + input); - 方案2:独立转换实现类
对于复用频率高的转换逻辑,直接编写独立的Transform子类,完全规避lambda使用,序列化安全性最高:
示例:
使用时直接创建实例加入Pipeline即可。// 字符串转Integer的独立实现 public class StringToIntTransform extends Transform { public StringToIntTransform() { super(String.class); } @Override public IOvariable process(IOvariable input) { String val = (String) input.getVariable(); return IOvariable.create(Integer.parseInt(val)); } } - 方案3:lambda序列化兼容改造
若保留lambda写法,需保证所有lambda无外部变量捕获,同时为ITransform接口显式声明serialVersionUID:
该方案稳定性依赖JDK版本与lambda实现,不推荐生产环境使用。@FunctionalInterface public interface ITransform<I, O> extends Serializable { long serialVersionUID = 1L; O process(I input); static <I, O> ITransform<I, O> of(ITransform<I, O> source) { return source; } }
内容的提问来源于stack exchange,提问作者rocksNwaves
相关产品推荐
相关产品推荐

