2017-05-05 14 views
6

特定の型の任意のオブジェクトのインスタンスメソッドへの参照が直列化可能かどうかを知りたいですか?インスタンスメソッドへの参照は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

+1

なぜ特定のタイプのメソッドリファレンスについて質問していますか?他のメソッド参照やラムダ式と比較して特別だと思いますか? – Holger

+0

私はあなたの質問が思考のための良い資料だと信じています。しかし、私はあなたのユースケースに興味があります...なぜメソッド参照をシリアル化する必要がありますか? –

+0

会話スコープのあるCDI Beanのフィールドです。したがって、直列化可能でなければなりません。 – Saljack

答えて

5

、メソッド参照は、シリアライズされます。あなたが求めている特定のタイプのメソッド参照について特別なことは何もありません。

「任意のオブジェクトのインスタンスメソッドへの参照」は、MyClassのインスタンスを取得していないため、MyClassSerializableではないことは重要ではありません。 object::fooのような特定のインスタンスのインスタンスメソッドを参照している場合は、オブジェクトが直列化されている必要があります。実行時にクラスが実装されていないとSerializableが失敗します。

voidメソッドを返品タイプVoidFunctionとして参照することはできません。私はあなたの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()); 
    } 
} 

としては、特定のインスタンスへの参照は、その直列化に依存し、したがって、ターゲット・インスタンスをシリアル化する必要があり、前記たとえば、あなたがSerializableを実装するために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と、実行時に失敗します。

+0

あなたの答えをありがとう。SerializableFunctionはSerializableを継承するインタフェースです。私の実際の戻り値の型はIntegerなので、これは私の間違いです。 – Saljack

0

私はあなたを知っていますラムダ式をシリアライズすることができます(here参照)

ここで、変数を単独でシリアル化するだけですか?なぜか、私はあなたができるとは思わない。たぶん、あなたは、ラムダを作成するように、他の道を行くと、それをシリアル化することができ、上記の記事のように:SerializableFunctionSerializableを拡張した型を参照すると仮定すると

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

静的変数は*シリアル化されません。たぶんあなたはあなたがリンクしているものを読んでください... – Holger

+0

ハハハハ私はダンクです、ありがとうございました...私は全く理解できない! –

関連する問題