Java 对象的哈希值是每次 hashCode() 方法调用重计算么?
对于没有覆盖hashCode()方法的对象
如果没有覆盖 hashCode() 方法,那么哈希值为底层 JDK C++ 源码实现,实例每次调用hashcode()方法,只有第一次计算哈希值,之后哈希值会存储在对象头的 标记字(MarkWord) 中。

如果进入各种锁状态,那么会缓存在其他地方,一般是获取锁的线程里面存储,恢复无锁(即释放锁)会改回原有的哈希值。
对应源码synchronizer.cpp:
//如果是无锁状态
if (mark.is_neutral()) {
hash = mark.hash();
//如果hash不等于0,证明计算过,直接返回
if (hash != 0) {
return hash;
}
//否则,计算hash值
hash = get_next_hash(self, obj); // get a new hash
//拷贝到Header中记录
temp = mark.copy_set_hash(hash);
test = obj->cas_set_mark(temp, mark);
//可能有并发,而且不同默认哈希值计算方法,可能每次哈希值不一样,只有 CAS 成功的才是最后的哈希值
//默认的哈希值计算,不论计算多少次,都不会变
if (test == mark) {
return hash;
}
} else if (mark.has_monitor()) {
//如果是有 monitor 锁状态(重量级锁),则获取其 monitor,哈希值会记录在monitor的头部
monitor = mark.monitor();
temp = monitor->header();
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
hash = temp.hash();
if (hash != 0) {
OrderAccess::loadload_for_IRIW();
if (monitor->is_being_async_deflated()) {
monitor->install_displaced_markword_in_object(obj);
continue;
}
return hash;
}
} else if (self->is_lock_owned((address)mark.locker())) {
// 如果是轻量级锁状态,获取轻量锁,其中也记录着之前计算的哈希值
temp = mark.displaced_mark_helper();
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
hash = temp.hash();
if (hash != 0) { // if it has a hash, just return it
return hash;
}
}
对于已经覆盖hashCode()方法的对象
对于已经覆盖hashCode()方法的对象,则每次都会重新调用hashCode()方法重新计算哈希值。
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:
Java 对象的哈希值是每次 hashCode() 方法调用重计算么?的更多相关文章
- 上传图片用图片文件的对象hash哈希值判断图片是否一样,避免重复提交相同的图片到服务器中
上传图片用图片文件的对象hash哈希值判断图片是否一样,避免重复提交相同的图片到服务器中 前端:要用到一个插件,点击下载 <!DOCTYPE html> <html xmlns=&q ...
- JAVA中获取文件MD5值的四种方法
JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现.获取文件MD5值主要分为三个步骤,第一步获取文件的byte信息,第二步通过Messa ...
- java基础解析系列(十一)---equals、==和hashcode方法
java基础解析系列(十一)---equals.==和hashcode方法 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系 ...
- 2021-2-17:Java HashMap 的中 key 的哈希值是如何计算的,为何这么计算?
首先,我们知道 HashMap 的底层实现是开放地址法 + 链地址法的方式来实现. 即数组 + 链表的实现方式,通过计算哈希值,找到数组对应的位置,如果已存在元素,就加到这个位置的链表上.在 Java ...
- 060、Java中定义有返回值有参数的方法
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- java中为什么重写equals时必须重写hashCode方法?
在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...
- Java反射获取对象VO的属性值(通过Getter方法)
有时候,需要动态获取对象的属性值. 比如,给你一个List,要你遍历这个List的对象的属性,而这个List里的对象并不固定.比如,这次User,下次可能是Company. e.g. 这次我需要做一个 ...
- java对象生成随意属性值
public class RandomObjectValue { public static <T> T getObject(Class<?> clazz) { T t = n ...
- java不同包中protected修饰的属性和方法调用方法
protected修饰的静态属性和方法的调用方式1:直接类名调用 2:实例化父类对象进行调用 3:实例化子类对象进行调用 protected修饰的非静态属性和方法的调用方式:1:实例化子类对象进行调用 ...
随机推荐
- 【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
任务描述 本次集中介绍使用Windows和Linux()搭建本地Redis服务器的步骤,从备份的RDB文件中加载数据,以及如何生成AOF文件和通过AOF文件想已经运行的Redis追加数据. 操作步骤 ...
- uni-app通过canvas实现手写签名
分享一个uni-app实现手写签名的方法 具体代码如下: <template> <view > <view class="title">请在下面 ...
- VGA调试心得
以前自己调试过视频信号,无非就时钟加行场同步加数据线,如果视频信号出问题,第一看现象,第二测频率,反正出问题不是消隐信号出问题,就是时钟频率出问题.通过这种方式也调试成功过几个显示屏,然后就以为自己对 ...
- 基于final shell的linux命令
final shell操作教程: 1.查看API实时日志:cd ../../data/log/api tail -100f anyAPI-server.log2.关闭日志:control+c3.恢复实 ...
- namedtuple
Python的namedtuple使用详解_kongxx的专栏-CSDN博客_namedtuple https://blog.csdn.net/kongxx/article/details/51553 ...
- (五)SpringBoot面试题
SpringBoot面试题 1.Spring Boot 的自动配置是如何实现的? 2.shiro和oauth还有cas他们之间的关系是什么?问下您公司权限是如何设计,还有就是这几个概念的区别. 2.1 ...
- HTML5 网页制作技巧
本文总结自由人民邮电出版社出版的<HTML.CSS.Javascript网页制作>. 总结进行学习,并分享给同样编写HTML5的朋友. 1:背景音乐的添加 <embed src=&q ...
- Linux常用命令,目录解析,思维导图
文章目录 下载地址 Linux常用命令 linux系统常用快捷键及符号命令 Linux常用Shell命令 Linux系统目录解析 Shell Vi全文本编辑器 Linux安装软件 Linux脚本编制编 ...
- 12.su 命令与sudo 服务
1.su 命令:解决切换用户身份的需求,使得当前用户在不退出登录的情况下,顺畅地切换到其他用户. 比如从root 管理员切换至普通用户: [root@Centos test]# id uid=0(r ...
- (23)gzip命令:压缩文件或目录&&gunzip命令:解压缩文件或目录
1.gzip 是 Linux 系统中经常用来对文件进行压缩和解压缩的命令,通过此命令压缩得到的新文件,其扩展名通常标记为".gz". 再强调一下,gzip 命令只能用来压缩文件,不 ...
