the*_*oop 13 java lambda serializable java-8
我正在编写一个可序列化的类,它带有几个参数,包括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;
}
}
Run Code Online (Sandbox Code Playgroud)
func
存储在成员变量中,因此需要可序列化.如果它们被分配的类型是可序列化的,则 Java lambdas 是可序列化的.Function
如果使用lambda创建,那么确保我在构造函数中传递的最佳方法是可序列化的?
创建一个SerializableFunction
类型并使用它:
public interface SerializableFunction<F, R> implements Function<F, R>, Serializable {}
....
public Cls(Collection<String> coll, SerializableFunction<String, ?> func) {...}
Run Code Online (Sandbox Code Playgroud)
问题:
coll
和func
参数之间存在不匹配,在func
签名中声明为可序列化,但coll
不是,但两者都需要可序列化才能工作.Function
可序列化.在构造函数上使用类型参数:
public <F extends Function<String, ?> & Serializable>
Cls(Collection<String> coll, F func) {...}
Run Code Online (Sandbox Code Playgroud)
问题:
func
参数需要Serializable
在编译时类型层次结构中实现,但coll
只需要以某种方式进行序列化(尽管如果需要可以抛弃此要求).编辑当尝试使用lambda或方法引用调用时,此代码实际上不会编译.
把它留给来电者
这要求调用者知道(来自javadoc或者试错)参数需要可序列化,并在适当时进行转换:
Cls c = new Cls(strList, (Function<String, ?> & Serializable)s -> ...);
Run Code Online (Sandbox Code Playgroud)
要么
Cls c = new Cls(strList, (Function<String, ?> & Serializable)Foo::processStr);
Run Code Online (Sandbox Code Playgroud)
这是丑陋的IMO,并且使用lambda的初始天真实现保证会中断,而不是像coll
(因为大多数集合以某种方式可序列化)一样工作.这也将类的实现细节推送到调用者.
目前我倾向于选择2,作为对呼叫者施加最小负担的选项,但我不认为这里有一个理想的解决方案.有关如何正确执行此操作的任何其他建议吗?
编辑:也许需要一些背景知识.这是一个在暴风雨中运行的类,在一个bolt中,它被序列化以传输到一个删除集群来执行.该功能在群集上运行时对已处理的元组执行操作.因此,它可以序列化并且函数参数是可序列化的,这是类的目的的很大一部分.如果不是,则该类根本不可用.
在大多数情况下,答案是:不要.
您可能会注意到JRE的大多数类,甚至ObjectOutputStream.writeObject
不会Serializable
在其签名中强制执行.有太多的API没有专门用于序列化,其中有关对象实现的编译时信息Serializable
丢失并且与序列化一起使用它们需要大量的类型转换,如果后者强制执行它们的输入Serializable
.
由于您的某个参数是a Collection
,您可以从该API获取示例:
如果指定的列表是可序列化的,则返回的列表将是可序列化的.
您将发现更多这些操作,这些操作需要保留序列化功能,而不会Serializable
在结果上保留编译时类型.
这也适用于所有非public
类型,例如Collections.emptyList()
,Arrays.asList(…)
和的结果Comparator.reverseOrder()
.他们都Serializable
没有宣布.
此外,每个具有更多用例而不仅仅是序列化的类应避免强制执行Serializable
.这将阻碍不涉及序列化的用途.
关于Collection
参数,您可以考虑删除可序列化约束.通常情况下,您可以保护您的课程免受以后对您收到的集合的更改.一个简单的解决方案是复制集合,当您执行此操作时,您可以使用支持序列化的类型.
即使您想避免复制,序列化本身也是一个复制过程本身,因此您可以简单地创建存储内容的自定义readObject
和writeObject
方法,从而无需拥有集合.Collection
Serializable
总而言之,通常的策略是,如果您的类的用户打算序列化它的实例,则用户有责任将所有组件放入其中Serializable
.
归档时间: |
|
查看次数: |
1145 次 |
最近记录: |