Lambda表达式是1.8特别重要的一个新增内容。
之前学习的时候,只注意了书上关于它的使用,语义等。直到前几天有个面试官问我:
问:Lambda表达式知道吗?
答:知道啊。(心里活动:问我问我,这个我前几天刚看过)
问:使用了Lambda表达式的对象可以序列化吗?为什么?
答:WTF???404 not find。您的问题超出了我的知识储备。
今天特地对这个问题进行了实验,顺便把Lambda和序列化进行再次复习。
关于Lambda和序列化的基础知识,咱们就不多说,随便一本java的书说的很清楚。推荐《Java核心技术》。
但是里面不会讲Lambda它能否序列化,以及为什么。
我百度了一下,很多答案是:默认不可以,但是用正确的方式,是可以进行序列化的。
我自己写了一个实验代码。(借鉴几行了博主:诸相非相的代码)
// main运行代码
public class CreatingStreams {
public static void main (String[] args){
Comparator cmp=new ComparatorFactory().makeComparator();
int i=10;
int j =-5;
System.out.println(cmp.compare(i, j));
try {
//写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(cmp);
obs.close();
System.out.println("a");
//分配内存,写入原始对象,生成新对象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
//返回生成的新对象
cmp = (Comparator)ois.readObject();
ois.close();
System.out.println("b");
} catch (Exception e) {
e.printStackTrace();
System.out.println("c");
}
System.out.println(cmp.compare(i, j));
}
}
public class ComparatorFactory{
public Comparator makeComparator(){
return (x,y)->Integer.compareUnsigned((int)x,(int)y);
}
}
代码较为简单,主要逻辑就是创建一个对象cmp(Comparator类型),使用Lambda表达式来实现该抽象函数。
看似没毛病,编译执行出错:
-1
c
-1
java.io.NotSerializableException: stream.ComparatorFactory$$Lambda$1/1791741888
可以看出,Lambda序列化出错。
我们仔细想一下,序列化对象是需要有实现序列化接口的。但这里我们并没有实现。implements Serializable
那么我们在哪里实现这个序列化接口呢?正常情况下,我们会在cmp对象的类定义时加上一句implements Serializable;
但是Comparator接口是没有这语句的...
那么我们怎么办?只能打开Comparator的代码,看看有没有什么发现。
发现里面有个默认方法,
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
该方法的具体用途我们就不说了,只需要看到return (Comparator<T> & Serializable) (c1,c2)->{exp}
是不是很眼熟??!!返回值里面带有类型转换!!!给Comparator<T>加上了Serializable的标志!!!
神操作啊,没想到吧,接口也可以进行类型转化的。
根据这个启发,我们修改一下我们的代码为
public class ComparatorFactory {
public Comparator makeComparator(){
return (Comparator&Serializable)(x,y)->Integer.compareUnsigned((int)x,(int)y);
}
}
再次运行,成功:
-1
a
b
-1
故而,Lambda是可以进行序列化的。
小白一枚,因为技术原因,写的一定有很多疏漏之处,还请大家批判性阅读。谢谢斧正。
(写博客初衷只是为了鞭策自己,好好学习)