【问题标题】:Is reference to an instance method serializable in Java 8?在 Java 8 中对实例方法的引用是否可序列化?
【发布时间】:2017-05-05 12:55:51
【问题描述】:

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

例子:

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;

已编辑

【问题讨论】:

  • 您为什么要询问那种特定类型的方法参考?你认为它与其他方法引用或 lambda 表达式相比有什么特别之处吗?
  • 我相信你的问题是很好的思考材料,所以我投了赞成票。不过,我很好奇您的用例……为什么需要序列化方法引用?
  • 它是具有会话范围的CDI bean 的字段。所以它必须是可序列化的。

标签: java-8


【解决方案1】:

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

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

什么不起作用,将void 方法引用为返回类型为VoidFunction。不知道你的SerializableFunction&lt;MyClass, Void&gt;是怎么定义的,但是如果等价于Function&lt;MyClass, Void&gt;&amp;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 更改为实现 Serializable

【讨论】:

  • 感谢您的回答。 SerializableFunction 是扩展 Serializable 的接口。我真正的返回类型是整数,所以这是我的错误。
【解决方案2】:

我知道您可以序列化 lambda 表达式(如您所见 here

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

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

【讨论】:

  • 静态变量没有序列化。也许您应该阅读链接的内容……
  • 哈哈哈哈哈哈我是个灌篮高手,太感谢你了……我很想念你!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
相关资源
最近更新 更多