如何为java对象生成校验和

问题描述 投票:14回答:10

我正在寻找一种解决方案来为任何类型的Java对象生成校验和,对于生成相同对象的应用程序的每次执行,它都保持不变。

我用Object.hashCode()尝试过,但api说

....从应用程序的一次执行到同一应用程序的另一次执行,这个整数不需要保持一致。

java object checksum
10个回答
9
投票

我有类似的问题(为XML文件生成良好的哈希码),我发现最好的解决方案是通过MessageDigest使用MD5,或者如果你需要更快的东西:Fast MD5。请注意,即使Object.hashCode每次无论如何太短(仅32位)都是相同的,以确保高唯一性。我认为64位是计算良好哈希码的最小值。请注意,MD5生成128位长的哈希码,在这种情况下应该更加需要。

当然要使用MessageDigest,你需要首先序列化(在你的情况下是marshall)对象。


0
投票
  1. 对象 - >字符串(例如,GSON - 您不必编写序列化而不是列出类的所有字段)
  2. String.hashCode() - > int(而不是Object.hashCode()!hashCode()的这种实现取决于String的内容,而不是内存中的地址---你可以在不同的应用程序启动,不同的线程等中使用它。)

(或2.字符串 - > md5)


13
投票
public static String getChecksum(Serializable object) throws IOException, NoSuchAlgorithmException {
    ByteArrayOutputStream baos = null;
    ObjectOutputStream oos = null;
    try {
        baos = new ByteArrayOutputStream();
        oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] thedigest = md.digest(baos.toByteArray());
        return DatatypeConverter.printHexBinary(thedigest);
    } finally {
        oos.close();
        baos.close();
    }
}

8
投票

private BigInteger checksum(Object obj) throws IOException, NoSuchAlgorithmException {

    if (obj == null) {
      return BigInteger.ZERO;   
    }

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(obj);
    oos.close();

    MessageDigest m = MessageDigest.getInstance("SHA1");
    m.update(baos.toByteArray());

    return new BigInteger(1, m.digest());
}

5
投票

我想你应该看看serialization。序列化机制需要解决类似的问题,因此您可以了解它是如何实现的。

但如果你描述了你试图解决的问题,你可能会得到更精确的解决方案。


4
投票

如果您控制源,则可以实现hashCode(),以便从一个执行到另一个执行保持一致。


3
投票

您是否希望能够为所有Java对象执行此操作?

在那种情况下hashCode()不起作用。

对于某些类,hashCode()有一个更严格的定义,可以保证执行中的平等。例如,String有一个明确定义的hashCode实现。类似地,ListSet具有明确定义的值,前提是它们包含的所有对象也具有明确定义的值(请注意,一般Collection.hashCode()不需要对值进行明确定义)。

对于其他类,您必须使用一些明确定义的公式递归地使用反射来构建校验和。


2
投票

Hashcode没问题。给定的班级覆盖equals以及合同要求hashcode。通过契约,如果equals返回true哈希码必须是相同的。 或者类不会覆盖equals。在这种情况下,应用程序的不同执行不能生成相同的对象,因此没有问题。 唯一的问题是某些类(甚至来自Java API)违反了equals的合同。


2
投票

如果你正在使用Eclipse IDE,那么它有动作(在Source菜单下)来生成hashcode和equals函数。它允许您在哈希码中选择所需类的属性。这类似于使用已经建议的HashCodeBuilder方法。

或者,您可以将对象流式传输到字节数组并生成MD5。


2
投票

Apache commons lang库提供了一个HashCodeBuilder类,它有助于构建一个哈希代码,满足您对类属性的要求。

例:

   public int checksum() {
     // you pick a hard-coded, randomly chosen, non-zero, odd number
     // ideally different for each class
     return new HashCodeBuilder(17, 37).
       append(property1).
       append(property2).
       append(property3).
       toHashCode();
   }

Commons Lang API

© www.soinside.com 2019 - 2024. All rights reserved.