Java中的判断相等问题,你踩过几个坑?
你好,我是猿java。
在业务开发中,判断相等的逻辑是很常见的,因为在java语言中有原生数据类型,包装类,引用等,如果判等使用不当,小则出现Bug,未能达到真实判等作用,重则可能会引起内存泄露等问题。
所以今天我们就来聊聊java中的判等的问题,看看你的日常开发中踩过几个坑。
判等操作
在java中常见的的判等操作有:equal、compareTo 和 ==。
温馨提示:单个 = 在java中是赋值的含义,不是数学中的等于号哦
数据类型
原生数据类型,8个
1
2
3
4
5
6
7
81)byte: 字节,1个字节,8位,-128~127
2)short:短整型,2个字节,16位
3)int: 整型,4个字节,32位
4)long: 长整型,8个字节,64位
5)float:单精度小数,例如:5.2
6)double:双精度浮点型
7)char: 单个的字符,例如字母a,或者中文张,char ch = 'a'; char b = '张';
8)boolean: 布尔类型,只有true和false包装数据类型,8个
1
2
3
4
5
6
7
81)Byte
2)Short
3)Int
4)Long
5)Float
6)Double
7)Char
8)Boolean引用类型
1
People people = new People(); people就为一个引用类型,指向new People()这个对象
equals、compareTo、 == 的使用和分析
我们先看几个使用例子,然后对照结果来讲解区别
1 | int a = 10; |
为什么integer1 == integer2; 为true,而integer3 == integer4; 为false?
这是因为对于Integer类型,当值在-128~127时,存在一个缓存的概念,源码如下:java.lang.Integer.valueOf(java.lang.String, int),同理,Long,Double也是一样,有兴趣的可以去看看源码。
1 | public final class Integer extends Number implements Comparable<Integer> { |
为什么obj1 == obj2; 为false,而integer1 == integer2; 和 a.equals(b); 都为true
这是因为Object的equals是比地址,而Integer等包装数据类型和String重写了equlas方法,源码如下:
1 | public class Object{ |
对于String类型这种特殊的类型,我们做更多的分析,首先看几个String使用的案例:
1 | // 案例1 |
对于String这种类型,为了节省内存,设计了字符串常量池机制。对于双引号的String,JVM会先对这个字符串进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回;否则,创建新的字符串对象,然后将这个引用放入字符串常量池,并返回该引用。这种机制,就是字符串驻留或池化。
对于引用类型,比较的是引用指向的内存地址是否一致,也就是比较它们是不是同一个对象。
案例1,a,b 都能在字符串常量池中找到,所以 a == b 为true;
案例2,a指向字符串常量池,b指向堆栈,所以 a == b 为false;
案例3,new 出来的两个String是不同对象,引用当然不同,所以 a == b 为false;
案例4,使用 String 提供的 intern 方法也会走常量池机制,所以 a == b 为true;
java.lang.String.intern()源码
1 | /** |
通过上面的源码注释可以知道intern()可以使字符串驻留的在常量池中,而字符串常量池是一个固定容量的Map,如果业务代码中使用了intern()方法,可能会导致性能问题。
案例5,equals是对值内容判等,所以 a == b 为true;
compareTo比较
将此对象与指定对象进行比较以进行排序。 返回一个负整数表示小于指定对象、零表示等于指定对象或正整数表示大于指定对象。源码如下:
1 | public interface Comparable<T> { |
总结
- 基本类型只能使用 ==,针对包装数据类型和 String 在内的引用类型,需要使用equals
- 除包装数据类型和 String 以外的引用类型,== 和 equals都是比地址,如果需要 equal是比值,就需要重写equals方法和hashCode方法
踩坑点
- 对于包装数据类型使用==比值,结果有时候对,有时候错
- 对于String类型,使用了new String(“”).intern(),导致性能问题
学习交流
如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。