3

我有一个HashMap密集的 Java 程序,其中几个类具有从final字段计算的哈希码。例如:

public class Foo {
    private final int bar;
    private final String zot;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + bar;
        result = prime * result + zot.hashCode();
        return result;
    }
}

编译器可能会观察到哈希码在对象初始化后无法更改,并将其预先计算到附加private final字段中。当前的 Java 编译器是否执行此操作,例如 Oracle JDK 7 中的编译器?我可以分解.class文件,但 JIT 也可能在运行时进行这种优化,我不会在那里看到它。无论如何,我对除此之外的其他情况感兴趣,因此找到一种通用方法来识别编译器自动执行的任何优化会很棒。

4

3 回答 3

6

当前的 Java 编译器是否执行此操作,例如 Oracle JDK 7 中的编译器?

javac几乎没有优化。

我可以分解 .class 文件,

您可能不喜欢您在优化方面看到的内容。;)

但是 JIT 也可能在运行时进行这种优化,我不会在那里看到它。

如果 JIT 确实对此进行了优化,您将看不到它,实际上它并没有这样做。这就是为什么 String 在运行时缓存它的 hashCode(),在代码中显式。

于 2013-09-27T01:58:13.467 回答
2

不,编译器不会这样做。但是,将哈希码自己存储在一个字段中并引用它而不是一直重新计算并不难:

private int hash = -1;

public int hashCode() {
    if (hash == -1) {
        // compute hash, assign it to the hash variable, and return it
    } else {
        return hash;
    }
}

这种方法实际上是由String该类采用的,如果您检查它的源代码,您可以看到:

121  /** Cache the hash code for the string */
122  private int hash; // Default to 0
于 2013-09-27T01:56:57.547 回答
1

编译器可以为任何合适的方法执行此操作,不仅如此,hashCode(),但事实并非如此。您可以通过javap -p是否有任何添加的字段自己查看,您还可以查看带有javap -c.

但是,您发布的方法不是合适的候选人。运行时的实现String.hashCode()可能与编译器可用的不同。编译器不能假设它不是。

于 2013-09-27T02:07:15.027 回答