equals问题
- 2.2 Object 类中的equals方法
- 2.3 Long类内的equals方法
- 2.4 String类内的equals方法
- 2.5 equals方法的使用规范。
2.5.1 Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。 - 2.5.2 所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
2.5.3 浮点数之间的等值判断,基本数据类型不能使用 == 进行比较,包装数据类型不能使用 equals - 2.5.4 BigDecimal 的等值比较应使用 compareTo() 方法,而不是 equals() 方法。
三: 总结
一:背景
代码里使用了一个equals来判断两个值是否相等,一个是long类型的,一个是string类型的,结果导致每次返回的都是false,每次都不相等。
在这里,我们分析一下对应原因并总结以后如何正确使用equals。
二:思路&方案
2.1 java的8中基本类型以及它对应的包装类
名称 | 类型 | 类型默认值 | 包装类 |
byte | 整数型 | 0 | Byte |
short | 整数型 | 0 | Short |
int | 整数型 | 0 | Integer |
long | 整数型 | 0L | Long |
float | 浮点型 | 0.0f | Float |
double | 浮点型 | 0.0d | Double |
boolean | 布尔型 | false | Boolean |
char | 字符型 | ‘u0000’ | Character |
2.2 Object 类中的equals方法
2.2 Object 类中的equals方法
public boolean equals(Object obj) { return (this == obj); }
== 是java中的比较运算符,如果是两个数值类型的话,就算数据类型不同,值相同,都会返回true。 如果是两个引用类型的话比较的是两个变量的内存地址。
2.3 Long类内的equals方法
public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; }
Long类内重写了Object类中的equals方法。做比较的时候,会先通过 instanceof (instanceof 是 Java 中的一个关键字,用于判断一个对象是否是某个类或其子类的实例。)判断传入的是不是Long类型,只有是相同类型的才会比较,如果不是相同类型就会直接返回false。这个就是我们上文提到的问题的原因。
Long类内重写了Object类中的equals方法。做比较的时候,会先通过 instanceof (instanceof 是 Java 中的一个关键字,用于判断一个对象是否是某个类或其子类的实例。)判断传入的是不是Long类型,只有是相同类型的才会比较,如果不是相同类型就会直接返回false。这个就是我们上文提到的问题的原因。
2.4 String类内的equals方法
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
String 类型的将会先进行 == 判断,也就是说,我们例子里提到的问题。如果将string写到前面就不会出问题。
2.5 equals方法的使用规范。
2.5.1 Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
正例:“test”.equals(param);
反例:param.equals(“test”);
说明:推荐使用 JDK7 引入的工具类 java.util.Objects#equals(Object a, Object b)
2.5.2 所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
说明:对于 Integer var = ? 在 -128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对
象,这个区间内的 Integer 值可以直接使用 == 进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复
用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
2.5.3 浮点数之间的等值判断,基本数据类型不能使用 == 进行比较,包装数据类型不能使用 equals
//说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表 //示大部分的十进制小数 //反例: float a = 1.0F - 0.9F; float b = 0.9F - 0.8F; if (a == b) { // 预期进入此代码块,执行其它业务逻辑 // 但事实上 a == b 的结果为 false } Float x = Float.valueOf(a); Float y = Float.valueOf(b); if (x.equals(y)) { // 预期进入此代码块,执行其它业务逻辑 // 但事实上 equals 的结果为 false } //正例: //(1)指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。 float a = 1.0F - 0.9F; float b = 0.9F - 0.8F; float diff = 1e-6F; if (Math.abs(a - b) < diff) { System.out.println("true"); } //(2)使用 BigDecimal 来定义值,再进行浮点数的运算操作。 BigDecimal a = new BigDecimal("1.0"); BigDecimal b = new BigDecimal("0.9"); BigDecimal c = new BigDecimal("0.8"); BigDecimal x = a.subtract(b); BigDecimal y = b.subtract(c); if (x.compareTo(y) == 0) { System.out.println("true"); }
2.5.4 BigDecimal 的等值比较应使用 compareTo() 方法,而不是 equals() 方法。
说明:equals() 方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo() 则会忽略精度
三: 总结
使用 JDK 带的方法时,必须要注意一些限制和规范,以避免滥用这些方法导致不必要的问题。以下是一些需要注意的事项:
3.1 不要滥用公共方法
JDK 中的许多方法都是公共方法,即可以被任何代码调用的方法。然而,公共方法可能会对应用程序的安全性和稳定性产生潜在风险,因此需要谨慎使用。
3.2 不要滥用底层方法
JDK 中的一些底层方法可以直接操作硬件或操作系统,这些方法具有高度的危险性,应该谨慎使用,避免对系统造成不必要的影响。
3.3 不要滥用过期方法
JDK 中的一些方法可能已经过时或不再推荐使用,应该避免在新的应用程序中使用这些方法,以避免出现不必要的问题。
3.4 不要滥用复杂方法
JDK 中的一些方法具有复杂的逻辑和复杂的参数设置,应该避免在简单的场景中滥用这些方法,以免影响程序的执行效率和可读性。
3.5总结
使用 JDK 带的方法时,需要充分理解方法的意义和用途,选择适合当前场景的方法,避免滥用方法造成不必要的问题。同时,也需要注意 JDK 版本的选择,避免使用已经废弃或不再支持的方法。
2.2 Object 类中的equals方法