【问题标题】:Serializing a class with Byte Array in Java用Java中的字节数组序列化一个类
【发布时间】:2015-04-12 06:34:46
【问题描述】:

我在 Java 中有一个带有字节数组的类。当我对类的对象进行序列化和反序列化时,Byte Array的值在变化。

我该如何解决这个问题?

请看示例代码:

public class Test implements Serializable{

private static final long serialVersionUID = 3455892176538865707L;
public byte[] datakey;

public static void main(String[] args) {

    byte[] key=new byte[16];    
    Random rn = new Random(); //Trying to randomize the byte array to use as a cryptographic key
    rn.nextBytes(key);

    Test test = new Test();
    test.datakey=key;
    System.out.println("Byte Array Before serialization : "+test.datakey);
    test.serializeTest(test);
    Test loadedtest=test.deserializeTest();
    System.out.println("Byte Array After deserialization : "+loadedtest.datakey);


}


public void serializeTest(Test test)
{

    FileOutputStream fos;
    try {

            fos = new FileOutputStream("test.out");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(test);
            oos.flush();
            oos.close();;
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

public Test deserializeTest()
{
    Test test=null; 
    String f="test.out";
    try
    {
            FileInputStream fis = new FileInputStream(f);
            ObjectInputStream ois = new ObjectInputStream(fis);
            test = (Test)ois.readObject();
            ois.close();
            fis.close();

    }
    catch(FileNotFoundException ex)
    {
            ex.printStackTrace();
    } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }

    return test;
}
}

输出:

Byte Array Before serialization : [B@15db9742
Byte Array After deserialization : [B@75b84c92

【问题讨论】:

  • sunil,请参阅我的答案,详细解释为什么您会获得序列化和反序列化对象的不同字符串表示形式。
  • 你没有打印字节数组的内容。

标签: java serialization bytearray deserialization


【解决方案1】:

字节数组的值没有改变。您只是在打印数组的 toString() 表示形式。

将使用来自java.lang.Object 的默认toString() 实现。

因为初始数组和反序列化数组不是同一个对象(它们是两个独立的对象,内容相同),所以它们会有不同的hashCode()Java 中的数组不会覆盖 equals()hashCode()

您应该改用Arrays.toString() 来打印数组的内容。

【讨论】:

  • 还是没有解释为什么输出中打印的hashcode值不一样?如果被序列化的数组与被反序列化的数组相同,hashcode不应该相等吗?
  • 因为数组不会覆盖 Java 中的 hashCode() 和 equals() 方法。
  • @Crazyjavahacking 你确定吗?毕竟,数组必须在内部使用类来实现。
  • @Crazyjavahacking 好吧,如果他们不覆盖 equals 和 hashCode,那就更有理由相信他们正在使用 hashcode 方法的默认实现,这解释了为什么我们在输出。看我的回答。
  • @Crazyjavahacking 看到这个。 stackoverflow.com/questions/2267790/…
【解决方案2】:

当您将对象传递给System.out.println() 方法时,将调用该对象的toString() 方法。

toString 方法的默认实现如下所示:

getClass().getName() + '@' + Integer.toHexString(hashCode())

在您的两个输出中,getClass().getName() 返回 [BInteger.toHexString(hashCode()) 返回不同的值。现在发生这种情况的唯一方法是序列化对象的hashCode() 与反序列化对象的不同。这正是发生的事情。虽然没有正式提及,hashCode() 的默认实现似乎是返回对象的内部地址。 hashCode() 方法的 javadocs 是这样说的:

在合理可行的情况下,hashCode 方法定义为 类 Object 确实为不同的对象返回不同的整数。 (这 通常是通过转换的内部地址来实现 对象转换成整数,但这种实现技术不是 JavaTM 编程语言所要求的。)

由于反序列化时序列化的对象很可能会加载到不同的地址,因此您会得到不同的hashCode 值,因此来自toString 的输出也不同

【讨论】:

  • getClass().getName() 实际上返回[B
  • @EJP。同意。已编辑。
  • hashcode不同的原因是对象不同。不同的对象必须加载到不同的地址,但这无关紧要。
  • 但不正确。它应该读作'因为反序列化对象与序列化对象不同,因此它将具有不同的哈希码,因此与toString(). 的输出不同
  • @EJP 同意。但我猜这是从两个语句中间接暗示的 1. 将使用默认的 hashCode 方法和 2. 反序列化时将序列化的对象加载到不同的地址。因此,暗示对象是不同的。
猜你喜欢
  • 2013-05-01
  • 2021-08-23
  • 1970-01-01
  • 2013-04-29
  • 2011-02-19
  • 2020-07-12
  • 2011-02-08
相关资源
最近更新 更多