War*_*ard 4 java generics lambda comparator java-8
我知道我们可以将函数转换为Serializable
需要它的位置.
但是,我想将此转换移动到通用方法,以使使用代码更简洁.我无法创建这样的方法.
我的具体问题是下面的地图不是Serializable
:
final Map<MyObject, String> map =
new TreeMap<>(Comparator.comparing(MyObject::getCode));
Run Code Online (Sandbox Code Playgroud)
我可以通过使用:
final Map<MyObject, String> map =
new TreeMap<>(Comparator.comparing((Function<MyObject, String> & Serializable) MyObject::getCode));
Run Code Online (Sandbox Code Playgroud)
但我希望能够做到这样的事情:
final Map<MyObject, String> map =
new TreeMap<>(Comparator.comparing(makeSerializable(MyObject::getCode)));
public static <T, U> Function<T, U> makeSerializable(Function<T, U> function) {
return (Function<T, U> & Serializable) function;
}
Run Code Online (Sandbox Code Playgroud)
对于编译器这很好,但在运行时,我得到一个ClassCastException
:
java.lang.ClassCastException: SerializableTest$$Lambda$1/801197928 cannot be cast to java.io.Serializable
Run Code Online (Sandbox Code Playgroud)
我也尝试了以下替代方案,但没有成功:
// ClassCastException
public static <T extends Serializable, U extends Serializable> Function<T, U> makeSerializable(Function<T, U> function) {
return (Function<T, U> & Serializable) function;
}
// No ClassCastException, but NotSerializableException upon Serializing
public static <T, U> Function<T, U> makeSerializable2(Function<T, U> function) {
return (Function<T, U> & Serializable) t -> function.apply(t);
}
Run Code Online (Sandbox Code Playgroud)
是否有可能创建这样的方法?
执行MyObject
:
static class MyObject implements Serializable {
private final String code;
MyObject(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
Run Code Online (Sandbox Code Playgroud)
是的,只要您不使用Function<T, U>
参数或结果的类型,就有可能.
相反,您可以创建自己的功能界面,既是Function
和Serializable
:
interface SerFunc<T, U> extends Function<T, U>, Serializable { }
Run Code Online (Sandbox Code Playgroud)
正如@ M.Prokhorov在评论中巧妙地建议的那样,你可以创建一个类似于你的方法的方法,但是接收并返回一个实例SerFunc
而不是Function
:
public static <T, U> SerFunc<T, U> makeSerializable(SerFunc<T, U> function) {
return function;
}
Run Code Online (Sandbox Code Playgroud)
此方法的唯一目标是Serializable
为方法引用或作为参数传递的lambda表达式提供目标类型.这就是为什么我们只是回归论证,即什么都不做.
现在您可以在代码中使用该方法,一切都可以正常工作:
Map<MyObject, String> map =
new TreeMap<>(Comparator.comparing(makeSerializable(MyObject::getCode)));
Run Code Online (Sandbox Code Playgroud)
至于你的尝试失败的原因,我想你可以找到回答这个问题的原因(@Eugene提供的链接),Brian Goetz解释说这个行为是设计的:
这是正确的,并且是设计的.正如您无法在实例化后获取非可序列化对象并使其可序列化一样,一旦创建了lambda,就会设置其可序列化.
如果lambda的目标类型是可序列化的(并且其捕获的参数是可序列化的),则lambda是可序列化的.
在您的尝试中,原始函数(由makeSerializable
方法作为参数接收)不是Serializable
,因此我们创建的任何使用此非可序列化函数(实际上是捕获的参数)的lambda也将是不可序列化的.
归档时间: |
|
查看次数: |
592 次 |
最近记录: |