本文主要记录java中的小坑。目前遇到的主要是类型转换、精度差异,相关的错误还有collections中的异常。
来源:做leetcode周赛时发现经常有人用python规避精度问题,作为头铁保守派,我想记录一下java中的问题(其实是除了java,区分32位64位的语言都适用,比如c++,go等)。
1. -2147483648
坑:-2147483648在32位下乘-1,得到自身。类似的问题,MAth.abs(Integer.MIN_VALUE)=-2147483648
理解
- -2147483648,这个数字是int的最小值,即Integer.MIN_VALUE。int是从-2147483648到2147483647。
- 众所周知计算机保存数字是用补码保存的,补码是什么?
对于正数:三码合一,原码反码补码都一样;负数的反码是原码的除符号位以外按位取反,补码是原码的按位取反+1。符号位:0表示正,1表示负。 - 2147483648是2的31次方,他的原码本应是100…000。第一个1在最高位,即第32位,但第32位是符号位,如果没有符号位的话,2147483648就表示不出来了,因为没有最前面的1的话,就变成了全0,和0重复了。
- -2147483648的原码是100…000,反码是111…111,补码是100…000,可以看出来,-2147483648的补码就是除了符号位的,全0。
解决
- 在有了基础概念以后,回到坑的描述,某一个数乘-1,对除了-2147483648和0的数来说,只要把符号位换掉就可以了,但-2147483648,乘-1(如果真能乘的话),=2147483648,直接溢出了,变成了0。
- 那么实际中的二进制乘法是如何执行的呢?
二进制数相乘可以直接按照十进制乘法进行,或者转化为十进制数后相乘,再将结果转化为二进制数。且无符号数和补码的乘法在数值位(即非符号位)是相同的。 - 100…000和111…111(-1的补码)相乘,得到了100…000。这还是原来的-2147483648。所以乘-1没有变。
结论
- 为什么int是从-2147483648到2147483647?因为0占了2147483648的位置,正数和0占了2进制数的一半,负数自己占了另一半。
- 为什么会有补码的存在?负数的补码是按位取反再+1,那如果不+1的话,-1的反码是111…110,一直到-2147483647会是100…000。那么111…111(全1)这个数字就没有被利用到,为了利用全1的数字,补码在反码的基础上+1,整体向前移动,给-2147483648留出了位置。
ps:二进制模2加是异或,我在想乘法的时候有混淆过。
2. deque 和stack
stack继承自vector 不推荐使用,栈应该用链表来实现。可以使用deque。
deque的实现类可用LinkedList和ArrayDeque,ArrayDeque性能更好,但不支持null,不支持在中间删除元素。
ps: 链表在中间删除元素很方便,取下一个节点的地址就好,而ArrayDeque是数组实现,数组删除中间元素不方便)。
为什么用deque?
https://www.xttblog.com/?p=3416
为什么 arrayDeque比LinkedList更好?
https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist
3. 用的JsonProperty注解和反序列化objectMapper的来源要相同
import com.fasterxml.jackson.annotation.JsonProperty;
import org.codehaus.jackson.annotate.JsonProperty;
4.框架引用的版本被覆盖
项目a引用了es版本是x,被项目b使用时,明明只有一个依赖源,但版本加载出来不是x,而是另一个版本y。最后发现是dependency management 中 依赖了springboot-dependencies,springboot-dependencies中指定了版本y,springboot-dependencies不光指定了elasticsearch.version,还在它的dependencyManagement中规定了elasticsearch的版本是它写的属性值。maven加载时先从这个地方规定的版本加载,忽略了后面我项目a中指定的版本。
相关:Maven依赖两大原则
1.第一声明者优先。
2.路径近者优先。
示例:https://blog.csdn.net/a1102325298/article/details/80230062
5. writeBytes传string导致中文乱码
DataOutputStream.writeBytes(String s)传递中文乱码
JAVA中的char是16位的,一个char存储一个中文字符,直接用writeBytes方法转换会变为8位,直接导致高8位丢失。从而导致中文乱码。
解决方法:
现转换为字节组,再write写入流。方法如下:
原方法:
out.writeBytes(json.toString());
新方法:
out.write(json.toString.getBytes());
或
IOUtils.write(json, out);

812

被折叠的 条评论
为什么被折叠?



