我有一个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也可以在运行时进行这种优化,我不会在那里看到它。无论如何,我对除了这个之外的其他情况感兴趣,所以找到一种识别编译器自动优化的一般方法会很棒。
答案 0 :(得分:6)
当前的Java编译器是否像Oracle JDK 7中那样执行此操作?
javac
几乎没有优化。
我可以解散.class文件,
您可能不喜欢在优化方面看到的内容。 ;)
但是JIT也可能在运行时进行这种优化,我不会在那里看到它。
如果JIT确实优化了这一点,你就不会看到它,事实上它不会这样做。这就是String在运行时缓存它的hashCode()的原因,明确地在代码中。
答案 1 :(得分: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
类进行的,如果你检查它source,你可以看到它:
121 /** Cache the hash code for the string */
122 private int hash; // Default to 0
答案 2 :(得分:1)
编译器可以为任何合适的方法执行此操作,而不仅仅是hashCode(),
,但事实并非如此。您可以通过javap -p
自行查看是否有任何添加的字段,您还可以使用javap -c
查看字节码。
但是,您发布的方法不适合。 String.hashCode()
在运行时的实现可能与编译器可用的实现不同。编译器不能假设它不是。