java - 从 Callable 返回的本地类的序列化

标签 java exception serialization anonymous-class callable

这是一个脑筋急转弯。

我知道这个实际代码在很多层面上都很糟糕。我的问题不是如何执行此操作(我知道静态初始化 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/

相关文章:

java - 使用面向方面的编程向方法提供数据

java - int 的三个异常(exception)

c# - 如何从 WCF 服务响应中删除 outerXML

java - Smile 与 JSON 之间的高效转换

.net - 如何在 Asp.Net Web api 中返回深度序列化对象(具有复杂类型属性)?

java - 哪个方法引用可以简化这个 lambda (Foo foo) -> foo.getName()?

java - hibernate : How to prevent SQL injection when the collection elements needs to check with `like` operator?

java - 如何从 Maven 依赖项创建更新包,该包仅与上次构建相比发生变化

c - 尝试显示列表时读取访问冲突 (0xCCCCCCD0)

python - 我们可以在 raise 声明后返回吗