是否可以引用Java 8中可序列化的实例方法?

时间:2017-05-05 12:55:51

标签: java-8

我想知道对特定类型的任意对象的实例方法的引用是否可序列化?

示例:

public class MyClass {
    public void foo() {
        System.out.println("Serializable");
    }
}

SerializableConsumer

@FunctionalInterface
public interface SerializableConsumer<T> extends Consumer<T>, Serializable {
}

和字段是:

SerializableConsumer<MyClass> serializableMethod = MyClass::foo;

EDITED

2 个答案:

答案 0 :(得分:6)

假设SerializableFunction引用扩展Serializable的类型,方法引用将是可序列化的。您要求的特定类型的方法参考没有什么特别之处。

最值得注意的是,“对任意对象的实例方法的引用”没有捕获MyClass的任何实例,因此,MyClass不是Serializable的事实不是重要。如果你引用像object::foo之类的特定实例的实例方法会有所不同,因为在这种情况下,对象也必须被序列化,如果它的类没有实现,它将在运行时失败Serializable

什么行不通,是将void方法称为返回类型Function的{​​{1}}。我不知道您的Void是如何定义的,但如果它等同于SerializableFunction<MyClass, Void>,则无效。

当您拥有适当的功能界面时,序列化方法参考是没有问题的:

Function<MyClass, Void>&Serializable

如上所述,对特定实例的引用必须序列化目标实例,因此,取决于该实例的可序列化性,所以

import java.io.*;
import java.util.function.Consumer;

public class MyClass {
    public void foo() {
        System.out.println("Serializable");
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Consumer<MyClass> consumer = (Consumer<MyClass>&Serializable)MyClass::foo;

        byte[] serialized;
        try(ByteArrayOutputStream baos=new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(consumer);
            oos.flush();
            serialized=baos.toByteArray();
        }

        Consumer<MyClass> deserialized;
        try(ByteArrayInputStream bais=new ByteArrayInputStream(serialized);
            ObjectInputStream ois=new ObjectInputStream(bais)) {
            deserialized = (Consumer<MyClass>)ois.readObject();
        }

        deserialized.accept(new MyClass());
    }
}

将在运行时使用import java.io.*; import java.util.function.Consumer; public class MyClass { public void foo() { System.out.println("Serializable"); } public static void main(String[] args) throws IOException, ClassNotFoundException { Runnable runnable = (Runnable&Serializable)new MyClass()::foo; byte[] serialized; try(ByteArrayOutputStream baos=new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(runnable); oos.flush(); serialized=baos.toByteArray(); } Runnable deserialized; try(ByteArrayInputStream bais=new ByteArrayInputStream(serialized); ObjectInputStream ois=new ObjectInputStream(bais)) { deserialized = (Runnable)ois.readObject(); } deserialized.run(); } } 失败,除非您更改java.io.NotSerializableException: MyClass以实施MyClass

答案 1 :(得分:0)

我知道你可以序列化一个lambda表达式(你可以看到here

现在,您想要做的只是自己序列化变量?还是方法?...我不知道为什么,但我认为你不能。也许你可以采取其他方式,比如创建一个lambda并序列化它,就像上面的帖子一样:

Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");