Java左值和右值的思考
本文最后更新于:2021年12月4日 下午
Java左值和右值的思考
前言
昨天做了一道LeetCode,用到小根堆「PriorityQueue」,其中一个操作让我困惑了很久。
- 小根堆存储的是原数组为负值的下标,则小根堆堆顶为最小负数的下标
- 本意是循环中,每次让最小负数取到相反数,变成一个正数
while (k-- > 0) nums[queue.peek()] = -nums[queue.poll()];
- 这一操作让我疑惑了很久,根据赋值表达式的性质,应该是从右计算到左,但是如果这样思考的话,就会让
poll
先进行,后面才peek
,这样下标的计算就出错了。
- 这一操作让我疑惑了很久,根据赋值表达式的性质,应该是从右计算到左,但是如果这样思考的话,就会让
断点分析
- 先直接测试
num[q.peek()] = -num[q.poll()]
这一写法
- 即成功将
num
的第一个元素变成相反数
- 将
q.peek()
抽取变量
- 按照预期「将 peek 的下标元素置为相反数」,提取变量,即下标,这种写法清晰明了
- 将
q.poll()
抽取变量
q.poll()
让堆顶出队,保存下来,但这改变堆结构,在下次 peek
就不再是原堆的最小值元素
- 最终影响到第二个元素,而不是第一个元素,不符合预期。
字节码分析
反编译 .class
文件,分析执行过程
num[q.peek()] = -num[q.poll()]
- 显然是先执行的
peek
后执行poll
,符合预期
- 将
q.peek()
抽取变量
- 也是按照预期执行
peek
后执行poll
- 将
q.poll()
抽取变量
- 先执行的
poll
后执行peek
,不符合预期
Summary
- 不能按照赋值表达式
=
从右向左运行的思想思考nums[queue.peek()] = -nums[queue.poll()];
- 最终的赋值的确会按照右向左执行「赋值操作」,完成 置相反数 的操作
- 但是从最终字节码的执行顺序来看,📌猜测:对于表达式的计算,会从左向右计算,将前序准备工作「取值」完成后,才进行写操作,赋值。
🔗Reference
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!