2015-09-25 2 views
6

HashMapSerializableキー/値はSerializableとしています。ハッシュマップがシリアライズ不可

しかし、それは私のために働いていない。いくつかの他のIOストリームを試しました。なし

提案がありますか?

テストコード

public class SimpleSerializationTest { 
    @Test 
    public void testHashMap() throws Exception { 
     HashMap<String, String> hmap = new HashMap<String, String>() {{ 
      put(new String("key"), new String("value")); 
     }}; 

     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     ObjectOutput out = null; 
     out = new ObjectOutputStream(bos); 
     out.writeObject(hmap); 
     byte[] yourBytes = bos.toByteArray(); 
     if (out != null) { 
      out.close(); 
     } 
     bos.close(); 

     ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes); 
     ObjectInput in = null; 
     in = new ObjectInputStream(bis); 
     Object o = in.readObject(); 
     bis.close(); 
     if (in != null) { 
      in.close(); 
     } 

     assertEquals(hmap, o); 
    } 
} 

例外メッセージは問題がある正確に何を説明します

java.io.NotSerializableException: SimpleSerializationTest 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) 
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) 
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) 
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) 
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) 
    at SimpleSerializationTest.testHashMap(SimpleSerializationTest.java:18) 

Process finished with exit code 0 
+0

が私のlocal.it上でそれを試みたがいずれかのexception.Itなしで実行されますが、適切なクラスファイルをインポートしていないようですか?あなたはそれを分かち合うことができますか? –

+1

''新しい文字列( "key") 'を書くのではなく、' 'key" 'を書くだけです。 '' key ''のようなリテラルはすでに 'String'オブジェクトです。その 'String'オブジェクトのコピーを明示的に作成する必要はありません。 – Jesper

答えて

15

スタックトレース:あなたは、クラスSimpleSerializationTestのインスタンスをシリアル化しようとしていることクラスは直列化できません。

なぜですか?さて、匿名の内部クラスSimpleSerializationTestを作成しました。これはHashMapに拡張され、そのクラスのインスタンスを直列化しようとしています。内部クラスは常に外部クラスの関連インスタンスへの参照を持ち、デフォルトでは直列化はそれらを走査しようとします。

私は、二重括弧{{ ... }}というシンタックスを、特別な意味を持っているかのように見ています。実際には2つの別々の構成要素であることを理解することが重要です。コンストラクタ呼び出しの直後に現れる外側の中カッコのペアは、内部クラス定義の境界を示します。内部のペアは、の任意のクラスボディで使用できるようなインスタンスイニシャライザブロックをバインドします(ただし、匿名の内部クラス以外のコンテキストでは異常です)。通常は、イニシャライザブロックの前または後に、外側のペアの中にメソッド実装/オーバーライドを1つ以上含めることもできます。

代わりにこれを試してください:あなたのコードの

public void testHashMap() throws Exception { 
     HashMap<String, String> hmap = new HashMap<String, String>(); 

     hmap.put(new String("key"), new String("value")); 

     // ... 
    } 
+0

意味がありますが、OPのコードを正確に実行すると、問題なくシリアル化されます。何故ですか? – sstan

+1

@sstanおそらくあなたは静的な状況からそれをやっていますか? – RealSkeptic

+0

@RealSkeptic:それだけです!それを指摘してくれてありがとう。 – sstan

0

作業バージョン:

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.ObjectInput; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutput; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import java.util.HashMap; 

import org.junit.Test; 

import junit.framework.Assert; 

public class SimpleSerializationTest implements Serializable{ 
    @Test 
public void testHashMap() throws Exception { 
    HashMap<String, String> hmap = new HashMap<String, String>() {{ 
     put(new String("key"), new String("value")); 
    }}; 

    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    ObjectOutput out = null; 
    out = new ObjectOutputStream(bos); 
    out.writeObject(hmap); 
    byte[] yourBytes = bos.toByteArray(); 
    if (out != null) { 
     out.close(); 
    } 
    bos.close(); 

    ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes); 
    ObjectInput in = null; 
     in = new ObjectInputStream(bis); 
     HashMap<String, String> o = (HashMap<String, String>) in.readObject(); 
     bis.close(); 
     if (in != null) { 
      in.close(); 
     } 

     Assert.assertEquals(hmap, o); 
    } 
} 
+1

さて、テストクラスに直列化できないインスタンスメンバーがない限り、いいです。ほとんどの状況下では、内部クラスと、それに関連するホストクラスへの依存がシリアライズ可能であることを避ける方が良いでしょう。 –

関連する問題