这是一个脑筋急转弯。
我知道这个实际代码在很多层面上都很糟糕。我的问题不是如何执行此操作(我知道静态初始化 block ),而是为什么这不起作用,以帮助我理解 Java 序列化。
为什么会这样
import java.io.*;
import java.util.*;
class Main {
static Comparator<String> COMPARE_STRING_LENGTH;
static {
class CompareStringReverse implements Comparator<String>, Serializable {
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
COMPARE_STRING_LENGTH = new CompareStringReverse();
}
public static void main(String[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test.ser"));
out.writeObject(new TreeSet<String>(COMPARE_STRING_LENGTH));
out.close();
}
}
此时
import java.io.*;
import java.util.*;
import java.util.concurrent.Callable;
class Main {
static Comparator<String> COMPARE_STRING_LENGTH = new Callable<Comparator<String>>() {
public Comparator<String> call() {
class CompareStringReverse implements Comparator<String>, Serializable {
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
return new CompareStringReverse();
}
}.call();
public static void main(String[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test.ser"));
out.writeObject(new TreeSet<String>(COMPARE_STRING_LENGTH));
out.close();
}
}
产量
Exception in thread "main" java.io.NotSerializableException: Main$1
最佳答案
嗯,“为什么”有点微妙。即使您的命名 类 ( CompareStringReverse
) 实现了 Serializable
,它嵌套在一个没有匿名的匿名类中。因此,它是一个内部类,并且隐式引用了封闭的匿名类的一个实例。例如,如果您运行:
javap -c Main$1$1CompareStringReverse
您会看到该字段:
final Main$1 this$0;
这就是序列化失败的原因。不过,您仍然可以轻松修复它:
interface SerializableCallable<T> extends Serializable, Callable<T> {}
...
static Comparator<String> COMPARE_STRING_LENGTH =
new SerializableCallable<Comparator<String>>() {
...
};
唯一显着的区别是匿名类现在实现了 Serializable
以及Callable<T>
.我认为没有任何方法可以为要实现的匿名类指定多个接口(interface)(即您必须创建额外的接口(interface)来组合两者),但我可能是错的。
所以现在命名的内部类实现了Serializable
,它的唯一字段的类型也是如此,所以一切正常。
关于java - 从 Callable 返回的本地类的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15177399/